home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Basic / Visual Basic.60 / VB98 / WIZARDS / PDWIZARD / SETUP1 / COMMON.BAS < prev    next >
Encoding:
BASIC Source File  |  1998-06-20  |  83.2 KB  |  2,355 lines

  1. Attribute VB_Name = "basCommon"
  2. Option Explicit
  3. Option Compare Text
  4.  
  5. '
  6. ' Global Constants
  7. '
  8.  
  9. Global Const gstrSEP_DIR$ = "\"                         ' Directory separator character
  10. Global Const gstrSEP_AMPERSAND$ = "@"
  11. Global Const gstrSEP_REGKEY$ = "\"                      ' Registration key separator character.
  12. Global Const gstrSEP_DRIVE$ = ":"                       ' Driver separater character, e.g., C:\
  13. Global Const gstrSEP_DIRALT$ = "/"                      ' Alternate directory separator character
  14. Global Const gstrSEP_EXT$ = "."                         ' Filename extension separator character
  15. Global Const gstrSEP_PROGID = "."
  16. Global Const gstrSEP_FILE$ = "|"                        ' Use the character for delimiting filename lists because it is not a valid character in a filename.
  17. Global Const gstrSEP_LIST = "|"
  18. Global Const gstrSEP_URL$ = "://"                       ' Separator that follows HPPT in URL address
  19. Global Const gstrSEP_URLDIR$ = "/"                      ' Separator for dividing directories in URL addresses.
  20.  
  21. Global Const gstrUNC$ = "\\"                            'UNC specifier \\
  22. Global Const gstrCOLON$ = ":"
  23. Global Const gstrSwitchPrefix1 = "-"
  24. Global Const gstrSwitchPrefix2 = "/"
  25. Global Const gstrCOMMA$ = ","
  26. Global Const gstrDECIMAL$ = "."
  27. Global Const gstrQUOTE$ = """"
  28. Global Const gstrCCOMMENT$ = "//"                       ' Comment specifier used in C, etc.
  29. Global Const gstrASSIGN$ = "="
  30. Global Const gstrINI_PROTOCOL = "Protocol"
  31. Global Const gstrREMOTEAUTO = "RA"
  32. Global Const gstrDCOM = "DCOM"
  33.  
  34. Global Const gintMAX_SIZE% = 255                        'Maximum buffer size
  35. Global Const gintMAX_PATH_LEN% = 260                    ' Maximum allowed path length including path, filename,
  36.                                                         ' and command line arguments for NT (Intel) and Win95.
  37. Global Const gintMAX_GROUPNAME_LEN% = 30                ' Maximum length that we allow for an NT 3.51 group name.
  38. Global Const gintMIN_BUTTONWIDTH% = 1200
  39. Global Const gsngBUTTON_BORDER! = 1.4
  40.  
  41. Global Const intDRIVE_REMOVABLE% = 2                    'Constants for GetDriveType
  42. Global Const intDRIVE_FIXED% = 3
  43. Global Const intDRIVE_REMOTE% = 4
  44. Global Const intDRIVE_CDROM% = 5
  45. Global Const intDRIVE_RAMDISK% = 6
  46.  
  47. Global Const gintNOVERINFO% = 32767                     'flag indicating no version info
  48.  
  49. 'File names
  50. Global Const gstrFILE_SETUP$ = "SETUP.LST"              'Name of setup information file
  51. Global Const gstrTEMP_DIR$ = "TEMP"
  52. Global Const gstrTMP_DIR$ = "TMP"
  53.  
  54. 'Share type macros for files
  55. Global Const mstrPRIVATEFILE = ""
  56. Global Const mstrSHAREDFILE = "$(Shared)"
  57.  
  58. 'INI File keys
  59. Global Const gstrINI_FILES$ = "Setup1 Files"                           'default section to install
  60. Global Const gstrINI_SETUP$ = "Setup"
  61. Global Const gstrINI_COLOR$ = "Color"
  62. Global Const gstrINI_BOOT$ = "Bootstrap"
  63. Global Const gstrINI_APPNAME$ = "Title"
  64. Global Const gstrINI_CABS$ = "Cabs"
  65. Global Const gstrINI_APPDIR$ = "DefaultDir"
  66. Global Const gstrINI_APPEXE$ = "AppExe"
  67. Global Const gstrINI_APPTOUNINSTALL = "AppToUninstall"
  68. Global Const gstrINI_APPPATH$ = "AppPath"
  69. Global Const gstrINI_FORCEUSEDEFDEST = "ForceUseDefDir"
  70. Global Const gstrINI_DEFGROUP$ = "DefProgramGroup"
  71. Global Const gstrINI_CABNAME$ = "CabFile"
  72. Global Const gsPRIVATE As String = "PrivateGroup"
  73.  
  74. Global Const gstrEXT_DEP$ = "DEP"
  75.  
  76. 'Setup information file macros
  77. Global Const gstrAPPDEST$ = "$(AppPath)"
  78. Global Const gstrWINDEST$ = "$(WinPath)"
  79. Global Const gstrFONTDEST$ = "$(Font)"
  80. Global Const gstrWINSYSDEST$ = "$(WinSysPath)"
  81. Global Const gstrWINSYSDESTSYSFILE$ = "$(WinSysPathSysFile)"
  82. Global Const gstrPROGRAMFILES$ = "$(ProgramFiles)"
  83. Global Const gstrCOMMONFILES$ = "$(CommonFiles)"
  84. Global Const gstrCOMMONFILESSYS$ = "$(CommonFilesSys)"
  85. Global Const gstrDAODEST$ = "$(MSDAOPath)"
  86. Global Const gstrDONOTINSTALL$ = "$(DoNotInstall)"
  87.  
  88. Global Const gsZERO As String = "0"
  89. 'Mouse Pointer Constants
  90. Global Const gintMOUSE_DEFAULT% = 0
  91.  
  92. 'MsgError() Constants
  93. Global Const MSGERR_ERROR = 1
  94. Global Const MSGERR_WARNING = 2
  95.  
  96. 'Shell Constants
  97. Global Const NORMAL_PRIORITY_CLASS      As Long = &H20&
  98. Global Const INFINITE                   As Long = -1&
  99.  
  100. Global Const STATUS_WAIT_0              As Long = &H0
  101. Global Const STATUS_ABANDONED_WAIT_0    As Long = &H80
  102. Global Const STATUS_USER_APC            As Long = &HC0
  103. Global Const STATUS_TIMEOUT             As Long = &H102
  104. Global Const STATUS_PENDING             As Long = &H103
  105.  
  106. Global Const WAIT_FAILED                As Long = &HFFFFFFFF
  107. Global Const WAIT_OBJECT_0              As Long = STATUS_WAIT_0
  108. Global Const WAIT_TIMEOUT               As Long = STATUS_TIMEOUT
  109.  
  110. Global Const WAIT_ABANDONED             As Long = STATUS_ABANDONED_WAIT_0
  111. Global Const WAIT_ABANDONED_0           As Long = STATUS_ABANDONED_WAIT_0
  112.  
  113. Global Const WAIT_IO_COMPLETION         As Long = STATUS_USER_APC
  114. Global Const STILL_ACTIVE               As Long = STATUS_PENDING
  115.  
  116. 'GetLocaleInfo constants
  117. Global Const LOCALE_FONTSIGNATURE = &H58&           ' font signature
  118. Global Const LOCALE_SLANGUAGE = &H2
  119. Global Const LOCALE_SABBREVLANGNAME = &H3
  120.  
  121. Global Const TCI_SRCFONTSIG = 3
  122.  
  123. Global Const LANG_CHINESE = &H4
  124. Global Const SUBLANG_CHINESE_TRADITIONAL = &H1           ' Chinese (Taiwan)
  125. Global Const SUBLANG_CHINESE_SIMPLIFIED = &H2            ' Chinese (PR China)
  126. Global Const CHARSET_CHINESESIMPLIFIED = 134
  127. Global Const CHARSET_CHINESEBIG5 = 136
  128.  
  129. Global Const LANG_JAPANESE = &H11
  130. Global Const CHARSET_SHIFTJIS = 128
  131.  
  132. Global Const LANG_KOREAN = &H12
  133. Global Const SUBLANG_KOREAN = &H1                        ' Korean (Extended Wansung)
  134. Global Const SUBLANG_KOREAN_JOHAB = &H2                  ' Korean (Johab)
  135. Global Const CHARSET_HANGEUL = 129
  136.  
  137. Public Type STARTUPINFO
  138.     cb              As Long
  139.     lpReserved      As Long
  140.     lpDesktop       As Long
  141.     lpTitle         As Long
  142.     dwX             As Long
  143.     dwY             As Long
  144.     dwXSize         As Long
  145.     dwYSize         As Long
  146.     dwXCountChars   As Long
  147.     dwYCountChars   As Long
  148.     dwFillAttribute As Long
  149.     dwFlags         As Long
  150.     wShowWindow     As Integer
  151.     cbReserved2     As Integer
  152.     lpReserved2     As Long
  153.     hStdInput       As Long
  154.     hStdOutput      As Long
  155.     hStdError       As Long
  156. End Type
  157.  
  158. Public Type PROCESS_INFORMATION
  159.     hProcess    As Long
  160.     hThread     As Long
  161.     dwProcessID As Long
  162.     dwThreadID  As Long
  163. End Type
  164.  
  165. Type OFSTRUCT
  166.     cBytes As Byte
  167.     fFixedDisk As Byte
  168.     nErrCode As Integer
  169.     nReserved1 As Integer
  170.     nReserved2 As Integer
  171.     szPathName As String * 256
  172. End Type
  173.  
  174. Type VERINFO                                            'Version FIXEDFILEINFO
  175.     'There is data in the following two dwords, but it is for Windows internal
  176.     '   use and we should ignore it
  177.     Ignore(1 To 8) As Byte
  178.     'Signature As Long
  179.     'StrucVersion As Long
  180.     FileVerPart2 As Integer
  181.     FileVerPart1 As Integer
  182.     FileVerPart4 As Integer
  183.     FileVerPart3 As Integer
  184.     ProductVerPart2 As Integer
  185.     ProductVerPart1 As Integer
  186.     ProductVerPart4 As Integer
  187.     ProductVerPart3 As Integer
  188.     FileFlagsMask As Long 'VersionFileFlags
  189.     FileFlags As Long 'VersionFileFlags
  190.     FileOS As Long 'VersionOperatingSystemTypes
  191.     FileType As Long
  192.     FileSubtype As Long 'VersionFileSubTypes
  193.     'I've never seen any data in the following two dwords, so I'll ignore them
  194.     Ignored(1 To 8) As Byte 'DateHighPart As Long, DateLowPart As Long
  195. End Type
  196.  
  197. Type PROTOCOL
  198.     strName As String
  199.     strFriendlyName As String
  200. End Type
  201.  
  202. Type OSVERSIONINFO 'for GetVersionEx API call
  203.     dwOSVersionInfoSize As Long
  204.     dwMajorVersion As Long
  205.     dwMinorVersion As Long
  206.     dwBuildNumber As Long
  207.     dwPlatformId As Long
  208.     szCSDVersion As String * 128
  209. End Type
  210.  
  211. Type LOCALESIGNATURE
  212.     lsUsb(3)          As Long
  213.     lsCsbDefault(1)   As Long
  214.     lsCsbSupported(1) As Long
  215. End Type
  216. Type FONTSIGNATURE
  217.     fsUsb(3) As Long
  218.     fsCsb(1) As Long
  219. End Type
  220. Type CHARSETINFO
  221.     ciCharset As Long
  222.     ciACP     As Long
  223.     fs        As FONTSIGNATURE
  224. End Type
  225.  
  226. Global Const OF_EXIST& = &H4000&
  227. Global Const OF_SEARCH& = &H400&
  228. Global Const HFILE_ERROR% = -1
  229.  
  230. '
  231. ' Global variables used for silent and SMS installation
  232. '
  233. Public gfSilent As Boolean                              ' Whether or not we are doing a silent install
  234. Public gstrSilentLog As String                          ' filename for output during silent install.
  235. Public gfSMS As Boolean                                 ' Whether or not we are doing an SMS silent install
  236. Public gstrMIFFile As String                            ' status output file for SMS
  237. Public gfSMSStatus As Boolean                           ' status of SMS installation
  238. Public gstrSMSDescription As String                     ' description string written to MIF file for SMS installation
  239. Public gfNoUserInput As Boolean                         ' True if either gfSMS or gfSilent is True
  240. Public gfDontLogSMS As Boolean                          ' Prevents MsgFunc from being logged to SMS (e.g., for confirmation messasges)
  241. Global Const MAX_SMS_DESCRIP = 255                      ' SMS does not allow description strings longer than 255 chars.
  242.  
  243. 'Variables for caching font values
  244. Private m_sFont As String                   ' the cached name of the font
  245. Private m_nFont As Integer                  ' the cached size of the font
  246. Private m_nCharset As Integer               ' the cached charset of the font
  247.  
  248.  
  249. Global Const gsSTARTMENUKEY As String = "$(Start Menu)"
  250. Global Const gsPROGMENUKEY As String = "$(Programs)"
  251. Global Const gsSTART As String = "StartIn"
  252. Global Const gsPARENT As String = "Parent"
  253.  
  254. '
  255. 'List of available protocols
  256. '
  257. Global gProtocol() As PROTOCOL
  258. Global gcProtocols As Integer
  259. '
  260. ' AXDist.exe and wint351.exe needed.  These are self extracting exes
  261. ' that install other files not installed by setup1.
  262. '
  263. Public gfAXDist As Boolean
  264. Global Const gstrFILE_AXDIST = "AXDIST.EXE"
  265. Public gstrAXDISTInstallPath As String
  266. Public gfAXDistChecked As Boolean
  267. Public gfMDag As Boolean
  268. Global Const gstrFILE_MDAG = "mdac_typ.exe"
  269. Global Const gstrFILE_MDAGARGS = " /q:a /c:""setup.exe /QN1"""
  270. Public gstrMDagInstallPath As String
  271. Public gfWINt351 As Boolean
  272. Global Const gstrFILE_WINT351 = "WINt351.EXE"
  273. Public gstrWINt351InstallPath As String
  274. Public gfWINt351Checked As Boolean
  275. '
  276. 'API/DLL Declarations for 32 bit SetupToolkit
  277. '
  278. Declare Function SetTime Lib "vb6stkit.dll" (ByVal strFileGetTime As String, ByVal strFileSetTime As String) As Integer
  279. Declare Function DLLSelfRegister Lib "vb6stkit.dll" (ByVal lpDllName As String) As Integer
  280. Declare Function RegisterTLB Lib "vb6stkit.dll" (ByVal lpTLBName As String) As Integer
  281. Declare Function OSfCreateShellLink Lib "vb6stkit.dll" Alias "fCreateShellLink" (ByVal lpstrFolderName As String, ByVal lpstrLinkName As String, ByVal lpstrLinkPath As String, ByVal lpstrLinkArguments As String, ByVal fPrivate As Long, ByVal sParent As String) As Long
  282. Declare Function OSfRemoveShellLink Lib "vb6stkit.dll" Alias "fRemoveShellLink" (ByVal lpstrFolderName As String, ByVal lpstrLinkName As String) As Long
  283. Declare Function GetSystemDefaultLCID Lib "Kernel32" () As Long
  284. Declare Function GetLocaleInfoLS Lib "Kernel32" Alias "GetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, lpLCData As LOCALESIGNATURE, ByVal cchData As Long) As Long
  285. Declare Function TranslateCharsetInfo Lib "gdi32" (lpSrc As Long, lpcs As CHARSETINFO, ByVal dwFlags As Long) As Long
  286.  
  287. Declare Sub CopyMemory Lib "Kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal ByteLen As Long)
  288. Declare Function WaitForSingleObject Lib "Kernel32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long
  289. Declare Function InputIdle Lib "user32" Alias "WaitForInputIdle" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long
  290. Declare Function CreateProcessA Lib "Kernel32" (ByVal lpApplicationName As Long, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
  291. Declare Function GetExitCodeProcess Lib "Kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
  292. Declare Function CloseHandle Lib "Kernel32" (ByVal hObject As Long) As Long
  293. Declare Function GetDiskFreeSpace Lib "Kernel32" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters As Long, lpTtoalNumberOfClusters As Long) As Long
  294. Declare Function OpenFile Lib "Kernel32" (ByVal lpFilename As String, lpReOpenBuff As OFSTRUCT, ByVal wStyle As Long) As Long
  295. Declare Function GetFullPathName Lib "Kernel32" Alias "GetFullPathNameA" (ByVal lpFilename As String, ByVal nBufferLength As Long, ByVal lpBuffer As String, ByVal lpFilePart As String) As Long
  296. Declare Function GetPrivateProfileString Lib "Kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal lSize As Long, ByVal lpFilename As String) As Long
  297. Declare Function WritePrivateProfileString Lib "Kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As Any, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lplFilename As String) As Long
  298. Declare Function GetPrivateProfileSection Lib "Kernel32" Alias "GetPrivateProfileSectionA" (ByVal lpAppName As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFilename As String) As Long
  299. Declare Function GetPrivateProfileSectionNames Lib "Kernel32" Alias "GetPrivateProfileSectionNamesA" (ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFilename As String) As Long
  300. Declare Function GetWindowsDirectory Lib "Kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
  301. Declare Function GetSystemDirectory Lib "Kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
  302. Declare Function GetDriveType32 Lib "Kernel32" Alias "GetDriveTypeA" (ByVal strWhichDrive As String) As Long
  303. Declare Function GetTempFilename32 Lib "Kernel32" Alias "GetTempFileNameA" (ByVal strWhichDrive As String, ByVal lpPrefixString As String, ByVal wUnique As Integer, ByVal lpTempFilename As String) As Long
  304. Declare Function GetTempPath Lib "Kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
  305. Declare Function SendMessageString Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
  306. Global Const LB_FINDSTRINGEXACT = &H1A2
  307. Global Const LB_ERR = (-1)
  308.  
  309. Declare Function GetUserDefaultLCID Lib "Kernel32" () As Long
  310. Declare Sub GetLocaleInfoA Lib "Kernel32" (ByVal lLCID As Long, ByVal lLCTYPE As Long, ByVal strLCData As String, ByVal lDataLen As Long)
  311.  
  312. Declare Function VerInstallFile Lib "version.dll" Alias "VerInstallFileA" (ByVal Flags&, ByVal SrcName$, ByVal DestName$, ByVal SrcDir$, ByVal DestDir$, ByVal CurrDir As Any, ByVal TmpName$, lpTmpFileLen&) As Long
  313. Declare Function GetFileVersionInfoSize Lib "version.dll" Alias "GetFileVersionInfoSizeA" (ByVal sFile As String, lpLen) As Long
  314. Declare Function GetFileVersionInfo Lib "version.dll" Alias "GetFileVersionInfoA" (ByVal sFile As String, ByVal lpIgnored As Long, ByVal lpSize As Long, ByVal lpBuf As Long) As Long
  315. Declare Function VerQueryValue Lib "version.dll" Alias "VerQueryValueA" (ByVal lpBuf As Long, ByVal szReceive As String, lpBufPtr As Long, lLen As Long) As Long
  316. Declare Function OSGetShortPathName Lib "Kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
  317. Declare Function GetVersionEx Lib "Kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
  318.  
  319. ' Reboot system code
  320. Public Const EWX_REBOOT = 2
  321. Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
  322.  
  323. '----------------------------------------------------------
  324. ' FUNCTION: GetWinPlatform
  325. ' Get the current windows platform.
  326. ' ---------------------------------------------------------
  327. Public Function GetWinPlatform() As Long
  328.     
  329.     Dim osvi As OSVERSIONINFO
  330.     Dim strCSDVersion As String
  331.     osvi.dwOSVersionInfoSize = Len(osvi)
  332.     If GetVersionEx(osvi) = 0 Then
  333.         Exit Function
  334.     End If
  335.     GetWinPlatform = osvi.dwPlatformId
  336. End Function
  337.  
  338. '-----------------------------------------------------------
  339. ' SUB: AddDirSep
  340. ' Add a trailing directory path separator (back slash) to the
  341. ' end of a pathname unless one already exists
  342. '
  343. ' IN/OUT: [strPathName] - path to add separator to
  344. '-----------------------------------------------------------
  345. '
  346. Sub AddDirSep(strPathName As String)
  347.     If Right(Trim(strPathName), Len(gstrSEP_URLDIR)) <> gstrSEP_URLDIR And _
  348.        Right(Trim(strPathName), Len(gstrSEP_DIR)) <> gstrSEP_DIR Then
  349.         strPathName = RTrim$(strPathName) & gstrSEP_DIR
  350.     End If
  351. End Sub
  352. '-----------------------------------------------------------
  353. ' SUB: AddURLDirSep
  354. ' Add a trailing URL path separator (forward slash) to the
  355. ' end of a URL unless one (or a back slash) already exists
  356. '
  357. ' IN/OUT: [strPathName] - path to add separator to
  358. '-----------------------------------------------------------
  359. '
  360. Sub AddURLDirSep(strPathName As String)
  361.     If Right(Trim(strPathName), Len(gstrSEP_URLDIR)) <> gstrSEP_URLDIR And _
  362.        Right(Trim(strPathName), Len(gstrSEP_DIR)) <> gstrSEP_DIR Then
  363.         strPathName = Trim(strPathName) & gstrSEP_URLDIR
  364.     End If
  365. End Sub
  366.  
  367. '-----------------------------------------------------------
  368. ' FUNCTION: FileExists
  369. ' Determines whether the specified file exists
  370. '
  371. ' IN: [strPathName] - file to check for
  372. '
  373. ' Returns: True if file exists, False otherwise
  374. '-----------------------------------------------------------
  375. '
  376. Function FileExists(ByVal strPathName As String) As Integer
  377.     Dim intFileNum As Integer
  378.  
  379.     On Error Resume Next
  380.  
  381.     '
  382.     ' If the string is quoted, remove the quotes.
  383.     '
  384.     strPathName = strUnQuoteString(strPathName)
  385.     '
  386.     'Remove any trailing directory separator character
  387.     '
  388.     If Right$(strPathName, 1) = gstrSEP_DIR Then
  389.         strPathName = Left$(strPathName, Len(strPathName) - 1)
  390.     End If
  391.  
  392.     '
  393.     'Attempt to open the file, return value of this function is False
  394.     'if an error occurs on open, True otherwise
  395.     '
  396.     intFileNum = FreeFile
  397.     Open strPathName For Input As intFileNum
  398.  
  399.     FileExists = IIf(Err = 0, True, False)
  400.  
  401.     Close intFileNum
  402.  
  403.     Err = 0
  404. End Function
  405.  
  406. '-----------------------------------------------------------
  407. ' FUNCTION: DirExists
  408. '
  409. ' Determines whether the specified directory name exists.
  410. ' This function is used (for example) to determine whether
  411. ' an installation floppy is in the drive by passing in
  412. ' something like 'A:\'.
  413. '
  414. ' IN: [strDirName] - name of directory to check for
  415. '
  416. ' Returns: True if the directory exists, False otherwise
  417. '-----------------------------------------------------------
  418. '
  419. Public Function DirExists(ByVal strDirName As String) As Integer
  420.     Const strWILDCARD$ = "*.*"
  421.  
  422.     Dim strDummy As String
  423.  
  424.     On Error Resume Next
  425.  
  426.     AddDirSep strDirName
  427.     strDummy = Dir$(strDirName & strWILDCARD, vbDirectory)
  428.     DirExists = Not (strDummy = vbNullString)
  429.  
  430.     Err = 0
  431. End Function
  432.  
  433. '-----------------------------------------------------------
  434. ' FUNCTION: GetDriveType
  435. ' Determine whether a disk is fixed, removable, etc. by
  436. ' calling Windows GetDriveType()
  437. '-----------------------------------------------------------
  438. '
  439. Function GetDriveType(ByVal intDriveNum As Integer) As Integer
  440.     '
  441.     ' This function expects an integer drive number in Win16 or a string in Win32
  442.     '
  443.     Dim strDriveName As String
  444.     
  445.     strDriveName = Chr$(Asc("A") + intDriveNum) & gstrSEP_DRIVE & gstrSEP_DIR
  446.     GetDriveType = CInt(GetDriveType32(strDriveName))
  447. End Function
  448.  
  449. '-----------------------------------------------------------
  450. ' FUNCTION: ReadProtocols
  451. ' Reads the allowable protocols from the specified file.
  452. '
  453. ' IN: [strInputFilename] - INI filename from which to read the protocols
  454. '     [strINISection] - Name of the INI section
  455. '-----------------------------------------------------------
  456. Function ReadProtocols(ByVal strInputFilename As String, ByVal strINISection As String) As Boolean
  457.     Dim intIdx As Integer
  458.     Dim fOk As Boolean
  459.     Dim strInfo As String
  460.     Dim intOffset As Integer
  461.     
  462.     intIdx = 0
  463.     fOk = True
  464.     Erase gProtocol
  465.     gcProtocols = 0
  466.     
  467.     Do
  468.         strInfo = ReadIniFile(strInputFilename, strINISection, gstrINI_PROTOCOL & Format$(intIdx + 1))
  469.         If strInfo <> vbNullString Then
  470.             intOffset = InStr(strInfo, gstrCOMMA)
  471.             If intOffset > 0 Then
  472.                 'The "ugly" name will be first on the line
  473.                 ReDim Preserve gProtocol(intIdx + 1)
  474.                 gcProtocols = intIdx + 1
  475.                 gProtocol(intIdx + 1).strName = Left$(strInfo, intOffset - 1)
  476.                 
  477.                 '... followed by the friendly name
  478.                 gProtocol(intIdx + 1).strFriendlyName = Mid$(strInfo, intOffset + 1)
  479.                 If (gProtocol(intIdx + 1).strName = "") Or (gProtocol(intIdx + 1).strFriendlyName = "") Then
  480.                     fOk = False
  481.                 End If
  482.             Else
  483.                 fOk = False
  484.             End If
  485.  
  486.             If Not fOk Then
  487.                 Exit Do
  488.             Else
  489.                 intIdx = intIdx + 1
  490.             End If
  491.         End If
  492.     Loop While strInfo <> vbNullString
  493.     
  494.     ReadProtocols = fOk
  495. End Function
  496.  
  497. '-----------------------------------------------------------
  498. ' FUNCTION: ResolveResString
  499. ' Reads resource and replaces given macros with given values
  500. '
  501. ' Example, given a resource number 14:
  502. '    "Could not read '|1' in drive |2"
  503. '   The call
  504. '     ResolveResString(14, "|1", "TXTFILE.TXT", "|2", "A:")
  505. '   would return the string
  506. '     "Could not read 'TXTFILE.TXT' in drive A:"
  507. '
  508. ' IN: [resID] - resource identifier
  509. '     [varReplacements] - pairs of macro/replacement value
  510. '-----------------------------------------------------------
  511. '
  512. Public Function ResolveResString(ByVal resID As Integer, ParamArray varReplacements() As Variant) As String
  513.     Dim intMacro As Integer
  514.     Dim strResString As String
  515.     
  516.     strResString = LoadResString(resID)
  517.     
  518.     ' For each macro/value pair passed in...
  519.     For intMacro = LBound(varReplacements) To UBound(varReplacements) Step 2
  520.         Dim strMacro As String
  521.         Dim strValue As String
  522.         
  523.         strMacro = varReplacements(intMacro)
  524.         On Error GoTo MismatchedPairs
  525.         strValue = varReplacements(intMacro + 1)
  526.         On Error GoTo 0
  527.         
  528.         ' Replace all occurrences of strMacro with strValue
  529.         Dim intPos As Integer
  530.         Do
  531.             intPos = InStr(strResString, strMacro)
  532.             If intPos > 0 Then
  533.                 strResString = Left$(strResString, intPos - 1) & strValue & Right$(strResString, Len(strResString) - Len(strMacro) - intPos + 1)
  534.             End If
  535.         Loop Until intPos = 0
  536.     Next intMacro
  537.     
  538.     ResolveResString = strResString
  539.     
  540.     Exit Function
  541.     
  542. MismatchedPairs:
  543.     Resume Next
  544. End Function
  545. '-----------------------------------------------------------
  546. ' SUB: GetLicInfoFromVBL
  547. ' Parses a VBL file name and extracts the license key for
  548. ' the registry and license information.
  549. '
  550. ' IN: [strVBLFile] - must be a valid VBL.
  551. '
  552. ' OUT: [strLicKey] - registry key to write license info to.
  553. '                    This key will be added to
  554. '                    HKEY_CLASSES_ROOT\Licenses.  It is a
  555. '                    guid.
  556. ' OUT: [strLicVal] - license information.  Usually in the
  557. '                    form of a string of cryptic characters.
  558. '-----------------------------------------------------------
  559. '
  560. Public Sub GetLicInfoFromVBL(strVBLFile As String, strLicKey As String, strLicVal As String)
  561.     Dim fn As Integer
  562.     Const strREGEDIT = "REGEDIT"
  563.     Const strLICKEYBASE = "HKEY_CLASSES_ROOT\Licenses\"
  564.     Dim strTemp As String
  565.     Dim posEqual As Integer
  566.     Dim fLicFound As Boolean
  567.     
  568.     fn = FreeFile
  569.     Open strVBLFile For Input Access Read Lock Read Write As #fn
  570.     '
  571.     ' Read through the file until we find a line that starts with strLICKEYBASE
  572.     '
  573.     fLicFound = False
  574.     Do While Not EOF(fn)
  575.         Line Input #fn, strTemp
  576.         strTemp = Trim(strTemp)
  577.         If Left$(strTemp, Len(strLICKEYBASE)) = strLICKEYBASE Then
  578.             '
  579.             ' We've got the line we want.
  580.             '
  581.             fLicFound = True
  582.             Exit Do
  583.         End If
  584.     Loop
  585.  
  586.     Close fn
  587.     
  588.     If fLicFound Then
  589.         '
  590.         ' Parse the data on this line to split out the
  591.         ' key and the license info.  The line should be
  592.         ' the form of:
  593.         ' "HKEY_CLASSES_ROOT\Licenses\<lickey> = <licval>"
  594.         '
  595.         posEqual = InStr(strTemp, gstrASSIGN)
  596.         If posEqual > 0 Then
  597.             strLicKey = Mid$(Trim(Left$(strTemp, posEqual - 1)), Len(strLICKEYBASE) + 1)
  598.             strLicVal = Trim(Mid$(strTemp, posEqual + 1))
  599.         End If
  600.     Else
  601.         strLicKey = vbNullString
  602.         strLicVal = vbNullString
  603.     End If
  604. End Sub
  605.  
  606.  '-----------------------------------------------------------
  607.  ' FUNCTION GetLongPathName
  608.  '
  609.  ' Retrieve the long pathname version of a path possibly
  610.  '   containing short subdirectory and/or file names
  611.  '-----------------------------------------------------------
  612.  '
  613.  Function GetLongPathName(ByVal strShortPath As String) As String
  614.     On Error GoTo 0
  615.     
  616.     MakeLongPath (strShortPath)
  617.     GetLongPathName = StripTerminator(strShortPath)
  618.  End Function
  619.  
  620.  '-----------------------------------------------------------
  621.  ' FUNCTION GetShortPathName
  622.  '
  623.  ' Retrieve the short pathname version of a path possibly
  624.  '   containing long subdirectory and/or file names
  625.  '-----------------------------------------------------------
  626.  '
  627.  Function GetShortPathName(ByVal strLongPath As String) As String
  628.      Const cchBuffer = 300
  629.      Dim strShortPath As String
  630.      Dim lResult As Long
  631.  
  632.      On Error GoTo 0
  633.      strShortPath = String(cchBuffer, Chr$(0))
  634.      lResult = OSGetShortPathName(strLongPath, strShortPath, cchBuffer)
  635.      If lResult = 0 Then
  636.          'Error 53 ' File not found
  637.          'Vegas#51193, just use the long name as this is usually good enough
  638.          GetShortPathName = strLongPath
  639.      Else
  640.          GetShortPathName = StripTerminator(strShortPath)
  641.      End If
  642.  End Function
  643.  
  644. '-----------------------------------------------------------
  645. ' FUNCTION: GetTempFilename
  646. ' Get a temporary filename for a specified drive and
  647. ' filename prefix
  648. ' PARAMETERS:
  649. '   strDestPath - Location where temporary file will be created.  If this
  650. '                 is an empty string, then the location specified by the
  651. '                 tmp or temp environment variable is used.
  652. '   lpPrefixString - First three characters of this string will be part of
  653. '                    temporary file name returned.
  654. '   wUnique - Set to 0 to create unique filename.  Can also set to integer,
  655. '             in which case temp file name is returned with that integer
  656. '             as part of the name.
  657. '   lpTempFilename - Temporary file name is returned as this variable.
  658. ' RETURN:
  659. '   True if function succeeds; false otherwise
  660. '-----------------------------------------------------------
  661. '
  662. Function GetTempFilename(ByVal strDestPath As String, ByVal lpPrefixString As String, ByVal wUnique As Integer, lpTempFilename As String) As Boolean
  663.     If strDestPath = vbNullString Then
  664.         '
  665.         ' No destination was specified, use the temp directory.
  666.         '
  667.         strDestPath = String(gintMAX_PATH_LEN, vbNullChar)
  668.         If GetTempPath(gintMAX_PATH_LEN, strDestPath) = 0 Then
  669.             GetTempFilename = False
  670.             Exit Function
  671.         End If
  672.     End If
  673.     lpTempFilename = String(gintMAX_PATH_LEN, vbNullChar)
  674.     GetTempFilename = GetTempFilename32(strDestPath, lpPrefixString, wUnique, lpTempFilename) > 0
  675.     lpTempFilename = StripTerminator(lpTempFilename)
  676. End Function
  677. '-----------------------------------------------------------
  678. ' FUNCTION: GetDefMsgBoxButton
  679. ' Decode the flags passed to the MsgBox function to
  680. ' determine what the default button is.  Use this
  681. ' for silent installs.
  682. '
  683. ' IN: [intFlags] - Flags passed to MsgBox
  684. '
  685. ' Returns: VB defined number for button
  686. '               vbOK        1   OK button pressed.
  687. '               vbCancel    2   Cancel button pressed.
  688. '               vbAbort     3   Abort button pressed.
  689. '               vbRetry     4   Retry button pressed.
  690. '               vbIgnore    5   Ignore button pressed.
  691. '               vbYes       6   Yes button pressed.
  692. '               vbNo        7   No button pressed.
  693. '-----------------------------------------------------------
  694. '
  695. Function GetDefMsgBoxButton(intFlags) As Integer
  696.     '
  697.     ' First determine the ordinal of the default
  698.     ' button on the message box.
  699.     '
  700.     Dim intButtonNum As Integer
  701.     Dim intDefButton As Integer
  702.     
  703.     If (intFlags And vbDefaultButton2) = vbDefaultButton2 Then
  704.         intButtonNum = 2
  705.     ElseIf (intFlags And vbDefaultButton3) = vbDefaultButton3 Then
  706.         intButtonNum = 3
  707.     Else
  708.         intButtonNum = 1
  709.     End If
  710.     '
  711.     ' Now determine the type of message box we are dealing
  712.     ' with and return the default button.
  713.     '
  714.     If (intFlags And vbRetryCancel) = vbRetryCancel Then
  715.         intDefButton = IIf(intButtonNum = 1, vbRetry, vbCancel)
  716.     ElseIf (intFlags And vbYesNoCancel) = vbYesNoCancel Then
  717.         Select Case intButtonNum
  718.             Case 1
  719.                 intDefButton = vbYes
  720.             Case 2
  721.                 intDefButton = vbNo
  722.             Case 3
  723.                 intDefButton = vbCancel
  724.             'End Case
  725.         End Select
  726.     ElseIf (intFlags And vbOKCancel) = vbOKCancel Then
  727.         intDefButton = IIf(intButtonNum = 1, vbOK, vbCancel)
  728.     ElseIf (intFlags And vbAbortRetryIgnore) = vbAbortRetryIgnore Then
  729.         Select Case intButtonNum
  730.             Case 1
  731.                 intDefButton = vbAbort
  732.             Case 2
  733.                 intDefButton = vbRetry
  734.             Case 3
  735.                 intDefButton = vbIgnore
  736.             'End Case
  737.         End Select
  738.     ElseIf (intFlags And vbYesNo) = vbYesNo Then
  739.         intDefButton = IIf(intButtonNum = 1, vbYes, vbNo)
  740.     Else
  741.         intDefButton = vbOK
  742.     End If
  743.     
  744.     GetDefMsgBoxButton = intDefButton
  745.     
  746. End Function
  747. '-----------------------------------------------------------
  748. ' FUNCTION: GetDiskSpaceFree
  749. ' Get the amount of free disk space for the specified drive
  750. '
  751. ' IN: [strDrive] - drive to check space for
  752. '
  753. ' Returns: Amount of free disk space, or -1 if an error occurs
  754. '-----------------------------------------------------------
  755. '
  756. Function GetDiskSpaceFree(ByVal strDrive As String) As Long
  757.     Dim strCurDrive As String
  758.     Dim lDiskFree As Long
  759.  
  760.     On Error Resume Next
  761.  
  762.     '
  763.     'Save the current drive
  764.     '
  765.     strCurDrive = Left$(CurDir$, 2)
  766.  
  767.     '
  768.     'Fixup drive so it includes only a drive letter and a colon
  769.     '
  770.     If InStr(strDrive, gstrSEP_DRIVE) = 0 Or Len(strDrive) > 2 Then
  771.         strDrive = Left$(strDrive, 1) & gstrSEP_DRIVE
  772.     End If
  773.  
  774.     '
  775.     'Change to the drive we want to check space for.  The DiskSpaceFree() API
  776.     'works on the current drive only.
  777.     '
  778.     ChDrive strDrive
  779.  
  780.     '
  781.     'If we couldn't change to the request drive, it's an error, otherwise return
  782.     'the amount of disk space free
  783.     '
  784.     If Err <> 0 Or (strDrive <> Left$(CurDir$, 2)) Then
  785.         lDiskFree = -1
  786.     Else
  787.         Dim lRet As Long
  788.         Dim lBytes As Long, lSect As Long, lClust As Long, lTot As Long
  789.         
  790.         lRet = GetDiskFreeSpace(vbNullString, lSect, lBytes, lClust, lTot)
  791.         On Error Resume Next
  792.         lDiskFree = (lBytes * lSect) * lClust
  793.         If Err Then lDiskFree = 2147483647
  794.     End If
  795.  
  796.     If lDiskFree = -1 Then
  797.         MsgError Error$ & vbLf & vbLf & ResolveResString(resDISKSPCERR) & strDrive, vbExclamation, gstrTitle
  798.     End If
  799.  
  800.     GetDiskSpaceFree = lDiskFree
  801.  
  802.     '
  803.     'Cleanup by setting the current drive back to the original
  804.     '
  805.     ChDrive strCurDrive
  806.  
  807.     Err = 0
  808. End Function
  809.  
  810. '-----------------------------------------------------------
  811. ' FUNCTION: GetUNCShareName
  812. '
  813. ' Given a UNC names, returns the leftmost portion of the
  814. ' directory representing the machine name and share name.
  815. ' E.g., given "\\SCHWEIZ\PUBLIC\APPS\LISTING.TXT", returns
  816. ' the string "\\SCHWEIZ\PUBLIC"
  817. '
  818. ' Returns a string representing the machine and share name
  819. '   if the path is a valid pathname, else returns NULL
  820. '-----------------------------------------------------------
  821. '
  822. Function GetUNCShareName(ByVal strFN As String) As Variant
  823.     GetUNCShareName = Null
  824.     If IsUNCName(strFN) Then
  825.         Dim iFirstSeparator As Integer
  826.         iFirstSeparator = InStr(3, strFN, gstrSEP_DIR)
  827.         If iFirstSeparator > 0 Then
  828.             Dim iSecondSeparator As Integer
  829.             iSecondSeparator = InStr(iFirstSeparator + 1, strFN, gstrSEP_DIR)
  830.             If iSecondSeparator > 0 Then
  831.                 GetUNCShareName = Left$(strFN, iSecondSeparator - 1)
  832.             Else
  833.                 GetUNCShareName = strFN
  834.             End If
  835.         End If
  836.     End If
  837. End Function
  838.  
  839. '-----------------------------------------------------------
  840. ' FUNCTION: GetWindowsSysDir
  841. '
  842. ' Calls the windows API to get the windows\SYSTEM directory
  843. ' and ensures that a trailing dir separator is present
  844. '
  845. ' Returns: The windows\SYSTEM directory
  846. '-----------------------------------------------------------
  847. '
  848. Function GetWindowsSysDir() As String
  849.     Dim strBuf As String
  850.  
  851.     strBuf = Space$(gintMAX_SIZE)
  852.  
  853.     '
  854.     'Get the system directory and then trim the buffer to the exact length
  855.     'returned and add a dir sep (backslash) if the API didn't return one
  856.     '
  857.     If GetSystemDirectory(strBuf, gintMAX_SIZE) > 0 Then
  858.         strBuf = StripTerminator(strBuf)
  859.         AddDirSep strBuf
  860.         
  861.         GetWindowsSysDir = strBuf
  862.     Else
  863.         GetWindowsSysDir = vbNullString
  864.     End If
  865. End Function
  866. '-----------------------------------------------------------
  867. ' SUB: TreatAsWin95
  868. '
  869. ' Returns True iff either we're running under Windows 95
  870. ' or we are treating this version of NT as if it were
  871. ' Windows 95 for registry and application loggin and
  872. ' removal purposes.
  873. '-----------------------------------------------------------
  874. '
  875. Function TreatAsWin95() As Boolean
  876.     If IsWindows95() Then
  877.         TreatAsWin95 = True
  878.     ElseIf NTWithShell() Then
  879.         TreatAsWin95 = True
  880.     Else
  881.         TreatAsWin95 = False
  882.     End If
  883. End Function
  884. '-----------------------------------------------------------
  885. ' FUNCTION: NTWithShell
  886. '
  887. ' Returns true if the system is on a machine running
  888. ' NT4.0 or greater.
  889. '-----------------------------------------------------------
  890. '
  891. Function NTWithShell() As Boolean
  892.  
  893.     If Not IsWindowsNT() Then
  894.         NTWithShell = False
  895.         Exit Function
  896.     End If
  897.     
  898.     Dim osvi As OSVERSIONINFO
  899.     Dim strCSDVersion As String
  900.     osvi.dwOSVersionInfoSize = Len(osvi)
  901.     If GetVersionEx(osvi) = 0 Then
  902.         Exit Function
  903.     End If
  904.     strCSDVersion = StripTerminator(osvi.szCSDVersion)
  905.     
  906.     'Is this Windows NT 4.0 or higher?
  907.     Const NT4MajorVersion = 4
  908.     Const NT4MinorVersion = 0
  909.     If (osvi.dwMajorVersion >= NT4MajorVersion) Then
  910.         NTWithShell = True
  911.     Else
  912.         NTWithShell = False
  913.     End If
  914.     
  915. End Function
  916. '-----------------------------------------------------------
  917. ' FUNCTION: IsDepFile
  918. '
  919. ' Returns true if the file passed to this routine is a
  920. ' dependency (*.dep) file.  We make this determination
  921. ' by verifying that the extension is .dep and that it
  922. ' contains version information.
  923. '-----------------------------------------------------------
  924. '
  925. Function fIsDepFile(strFilename As String) As Boolean
  926.     Const strEXT_DEP = "DEP"
  927.     
  928.     fIsDepFile = False
  929.     
  930.     If UCase(Extension(strFilename)) = strEXT_DEP Then
  931.         If GetFileVersion(strFilename) <> vbNullString Then
  932.             fIsDepFile = True
  933.         End If
  934.     End If
  935. End Function
  936.  
  937. '-----------------------------------------------------------
  938. ' FUNCTION: IsWin32
  939. '
  940. ' Returns true if this program is running under Win32 (i.e.
  941. '   any 32-bit operating system)
  942. '-----------------------------------------------------------
  943. '
  944. Function IsWin32() As Boolean
  945.     IsWin32 = (IsWindows95() Or IsWindowsNT())
  946. End Function
  947.  
  948. '-----------------------------------------------------------
  949. ' FUNCTION: IsWindows95
  950. '
  951. ' Returns true if this program is running under Windows 95
  952. '   or successor
  953. '-----------------------------------------------------------
  954. '
  955. Function IsWindows95() As Boolean
  956.     Const dwMask95 = &H1&
  957.     IsWindows95 = (GetWinPlatform() And dwMask95)
  958. End Function
  959.  
  960. '-----------------------------------------------------------
  961. ' FUNCTION: IsWindowsNT
  962. '
  963. ' Returns true if this program is running under Windows NT
  964. '-----------------------------------------------------------
  965. '
  966. Function IsWindowsNT() As Boolean
  967.     Const dwMaskNT = &H2&
  968.     IsWindowsNT = (GetWinPlatform() And dwMaskNT)
  969. End Function
  970.  
  971. '-----------------------------------------------------------
  972. ' FUNCTION: IsWindowsNT4WithoutSP2
  973. '
  974. ' Determines if the user is running under Windows NT 4.0
  975. ' but without Service Pack 2 (SP2).  If running under any
  976. ' other platform, returns False.
  977. '
  978. ' IN: [none]
  979. '
  980. ' Returns: True if and only if running under Windows NT 4.0
  981. ' without at least Service Pack 2 installed.
  982. '-----------------------------------------------------------
  983. '
  984. Function IsWindowsNT4WithoutSP2() As Boolean
  985.     IsWindowsNT4WithoutSP2 = False
  986.     
  987.     If Not IsWindowsNT() Then
  988.         Exit Function
  989.     End If
  990.     
  991.     Dim osvi As OSVERSIONINFO
  992.     Dim strCSDVersion As String
  993.     osvi.dwOSVersionInfoSize = Len(osvi)
  994.     If GetVersionEx(osvi) = 0 Then
  995.         Exit Function
  996.     End If
  997.     strCSDVersion = StripTerminator(osvi.szCSDVersion)
  998.     
  999.     'Is this Windows NT 4.0?
  1000.     Const NT4MajorVersion = 4
  1001.     Const NT4MinorVersion = 0
  1002.     If (osvi.dwMajorVersion <> NT4MajorVersion) Or (osvi.dwMinorVersion <> NT4MinorVersion) Then
  1003.         'No.  Return False.
  1004.         Exit Function
  1005.     End If
  1006.     
  1007.     'If no service pack is installed, or if Service Pack 1 is
  1008.     'installed, then return True.
  1009.     Const strSP1 = "SERVICE PACK 1"
  1010.     If strCSDVersion = "" Then
  1011.         IsWindowsNT4WithoutSP2 = True 'No service pack installed
  1012.     ElseIf strCSDVersion = strSP1 Then
  1013.         IsWindowsNT4WithoutSP2 = True 'Only SP1 installed
  1014.     End If
  1015. End Function
  1016.  
  1017. '-----------------------------------------------------------
  1018. ' FUNCTION: IsUNCName
  1019. '
  1020. ' Determines whether the pathname specified is a UNC name.
  1021. ' UNC (Universal Naming Convention) names are typically
  1022. ' used to specify machine resources, such as remote network
  1023. ' shares, named pipes, etc.  An example of a UNC name is
  1024. ' "\\SERVER\SHARE\FILENAME.EXT".
  1025. '
  1026. ' IN: [strPathName] - pathname to check
  1027. '
  1028. ' Returns: True if pathname is a UNC name, False otherwise
  1029. '-----------------------------------------------------------
  1030. '
  1031. Function IsUNCName(ByVal strPathName As String) As Integer
  1032.     Const strUNCNAME$ = "\\//\"        'so can check for \\, //, \/, /\
  1033.  
  1034.     IsUNCName = ((InStr(strUNCNAME, Left$(strPathName, 2)) > 0) And _
  1035.                  (Len(strPathName) > 1))
  1036. End Function
  1037. '-----------------------------------------------------------
  1038. ' FUNCTION: LogSilentMsg
  1039. '
  1040. ' If this is a silent install, this routine writes
  1041. ' a message to the gstrSilentLog file.
  1042. '
  1043. ' IN: [strMsg] - The message
  1044. '
  1045. ' Normally, this routine is called inlieu of displaying
  1046. ' a MsgBox and strMsg is the same message that would
  1047. ' have appeared in the MsgBox
  1048.  
  1049. '-----------------------------------------------------------
  1050. '
  1051. Sub LogSilentMsg(strMsg As String)
  1052.     If Not gfSilent Then Exit Sub
  1053.     
  1054.     Dim fn As Integer
  1055.     
  1056.     On Error Resume Next
  1057.     
  1058.     fn = FreeFile
  1059.     
  1060.     Open gstrSilentLog For Append As fn
  1061.     Print #fn, strMsg
  1062.     Close fn
  1063.     Exit Sub
  1064. End Sub
  1065. '-----------------------------------------------------------
  1066. ' FUNCTION: LogSMSMsg
  1067. '
  1068. ' If this is a SMS install, this routine appends
  1069. ' a message to the gstrSMSDescription string.  This
  1070. ' string will later be written to the SMS status
  1071. ' file (*.MIF) when the installation completes (success
  1072. ' or failure).
  1073. '
  1074. ' Note that if gfSMS = False, not message will be logged.
  1075. ' Therefore, to prevent some messages from being logged
  1076. ' (e.g., confirmation only messages), temporarily set
  1077. ' gfSMS = False.
  1078. '
  1079. ' IN: [strMsg] - The message
  1080. '
  1081. ' Normally, this routine is called inlieu of displaying
  1082. ' a MsgBox and strMsg is the same message that would
  1083. ' have appeared in the MsgBox
  1084. '-----------------------------------------------------------
  1085. '
  1086. Sub LogSMSMsg(strMsg As String)
  1087.     If Not gfSMS Then Exit Sub
  1088.     '
  1089.     ' Append the message.  Note that the total
  1090.     ' length cannot be more than 255 characters, so
  1091.     ' truncate anything after that.
  1092.     '
  1093.     gstrSMSDescription = Left(gstrSMSDescription & strMsg, MAX_SMS_DESCRIP)
  1094. End Sub
  1095.  
  1096. '-----------------------------------------------------------
  1097. ' FUNCTION: MakePathAux
  1098. '
  1099. ' Creates the specified directory path.
  1100. '
  1101. ' No user interaction occurs if an error is encountered.
  1102. ' If user interaction is desired, use the related
  1103. '   MakePathAux() function.
  1104. '
  1105. ' IN: [strDirName] - name of the dir path to make
  1106. '
  1107. ' Returns: True if successful, False if error.
  1108. '-----------------------------------------------------------
  1109. '
  1110. Function MakePathAux(ByVal strDirName As String) As Boolean
  1111.     Dim strPath As String
  1112.     Dim intOffset As Integer
  1113.     Dim intAnchor As Integer
  1114.     Dim strOldPath As String
  1115.  
  1116.     On Error Resume Next
  1117.  
  1118.     '
  1119.     'Add trailing backslash
  1120.     '
  1121.     If Right$(strDirName, 1) <> gstrSEP_DIR Then
  1122.         strDirName = strDirName & gstrSEP_DIR
  1123.     End If
  1124.  
  1125.     strOldPath = CurDir$
  1126.     MakePathAux = False
  1127.     intAnchor = 0
  1128.  
  1129.     '
  1130.     'Loop and make each subdir of the path separately.
  1131.     '
  1132.     intOffset = InStr(intAnchor + 1, strDirName, gstrSEP_DIR)
  1133.     intAnchor = intOffset 'Start with at least one backslash, i.e. "C:\FirstDir"
  1134.     Do
  1135.         intOffset = InStr(intAnchor + 1, strDirName, gstrSEP_DIR)
  1136.         intAnchor = intOffset
  1137.  
  1138.         If intAnchor > 0 Then
  1139.             strPath = Left$(strDirName, intOffset - 1)
  1140.             ' Determine if this directory already exists
  1141.             Err = 0
  1142.             ChDir strPath
  1143.             If Err Then
  1144.                 ' We must create this directory
  1145.                 Err = 0
  1146. #If LOGGING Then
  1147.                 NewAction gstrKEY_CREATEDIR, """" & strPath & """"
  1148. #End If
  1149.                 MkDir strPath
  1150. #If LOGGING Then
  1151.                 If Err Then
  1152.                     LogError ResolveResString(resMAKEDIR) & " " & strPath
  1153.                     AbortAction
  1154.                     GoTo Done
  1155.                 Else
  1156.                     CommitAction
  1157.                 End If
  1158. #End If
  1159.             End If
  1160.         End If
  1161.     Loop Until intAnchor = 0
  1162.  
  1163.     MakePathAux = True
  1164. Done:
  1165.     ChDir strOldPath
  1166.  
  1167.     Err = 0
  1168. End Function
  1169.  
  1170. '-----------------------------------------------------------
  1171. ' FUNCTION: MsgError
  1172. '
  1173. ' Forces mouse pointer to default, calls VB's MsgBox
  1174. ' function, and logs this error and (32-bit only)
  1175. ' writes the message and the user's response to the
  1176. ' logfile (32-bit only)
  1177. '
  1178. ' IN: [strMsg] - message to display
  1179. '     [intFlags] - MsgBox function type flags
  1180. '     [strCaption] - caption to use for message box
  1181. '     [intLogType] (optional) - The type of logfile entry to make.
  1182. '                   By default, creates an error entry.  Use
  1183. '                   the MsgWarning() function to create a warning.
  1184. '                   Valid types as MSGERR_ERROR and MSGERR_WARNING
  1185. '
  1186. ' Returns: Result of MsgBox function
  1187. '-----------------------------------------------------------
  1188. '
  1189. Function MsgError(ByVal strMsg As String, ByVal intFlags As Integer, ByVal strCaption As String, Optional ByVal intLogType As Integer = MSGERR_ERROR) As Integer
  1190.     Dim iRet As Integer
  1191.     
  1192.     iRet = MsgFunc(strMsg, intFlags, strCaption)
  1193.     MsgError = iRet
  1194. #If LOGGING Then
  1195.     ' We need to log this error and decode the user's response.
  1196.     Dim strID As String
  1197.     Dim strLogMsg As String
  1198.  
  1199.     Select Case iRet
  1200.         Case vbOK
  1201.             strID = ResolveResString(resLOG_vbok)
  1202.         Case vbCancel
  1203.             strID = ResolveResString(resLOG_vbCancel)
  1204.         Case vbAbort
  1205.             strID = ResolveResString(resLOG_vbabort)
  1206.         Case vbRetry
  1207.             strID = ResolveResString(resLOG_vbretry)
  1208.         Case vbIgnore
  1209.             strID = ResolveResString(resLOG_vbignore)
  1210.         Case vbYes
  1211.             strID = ResolveResString(resLOG_vbyes)
  1212.         Case vbNo
  1213.             strID = ResolveResString(resLOG_vbno)
  1214.         Case Else
  1215.             strID = ResolveResString(resLOG_IDUNKNOWN)
  1216.         'End Case
  1217.     End Select
  1218.  
  1219.     strLogMsg = strMsg & vbLf & "(" & ResolveResString(resLOG_USERRESPONDEDWITH, "|1", strID) & ")"
  1220.     On Error Resume Next
  1221.     Select Case intLogType
  1222.         Case MSGERR_WARNING
  1223.             LogWarning strLogMsg
  1224.         Case MSGERR_ERROR
  1225.             LogError strLogMsg
  1226.         Case Else
  1227.             LogError strLogMsg
  1228.         'End Case
  1229.     End Select
  1230. #End If
  1231. End Function
  1232.  
  1233. '-----------------------------------------------------------
  1234. ' FUNCTION: MsgFunc
  1235. '
  1236. ' Forces mouse pointer to default and calls VB's MsgBox
  1237. ' function.  See also MsgError.
  1238. '
  1239. ' IN: [strMsg] - message to display
  1240. '     [intFlags] - MsgBox function type flags
  1241. '     [strCaption] - caption to use for message box
  1242. ' Returns: Result of MsgBox function
  1243. '-----------------------------------------------------------
  1244. '
  1245. Function MsgFunc(ByVal strMsg As String, ByVal intFlags As Integer, ByVal strCaption As String) As Integer
  1246.     Dim intOldPointer As Integer
  1247.   
  1248.     intOldPointer = Screen.MousePointer
  1249.     If gfNoUserInput Then
  1250.         MsgFunc = GetDefMsgBoxButton(intFlags)
  1251.         If gfSilent = True Then
  1252.             LogSilentMsg strMsg
  1253.         End If
  1254.         If gfSMS = True Then
  1255.             LogSMSMsg strMsg
  1256.             gfDontLogSMS = False
  1257.         End If
  1258.     Else
  1259.         Screen.MousePointer = gintMOUSE_DEFAULT
  1260.         MsgFunc = MsgBox(strMsg, intFlags, strCaption)
  1261.         Screen.MousePointer = intOldPointer
  1262.     End If
  1263. End Function
  1264.  
  1265. '-----------------------------------------------------------
  1266. ' FUNCTION: MsgWarning
  1267. '
  1268. ' Forces mouse pointer to default, calls VB's MsgBox
  1269. ' function, and logs this error and (32-bit only)
  1270. ' writes the message and the user's response to the
  1271. ' logfile (32-bit only)
  1272. '
  1273. ' IN: [strMsg] - message to display
  1274. '     [intFlags] - MsgBox function type flags
  1275. '     [strCaption] - caption to use for message box
  1276. '
  1277. ' Returns: Result of MsgBox function
  1278. '-----------------------------------------------------------
  1279. '
  1280. Function MsgWarning(ByVal strMsg As String, ByVal intFlags As Integer, ByVal strCaption As String) As Integer
  1281.     MsgWarning = MsgError(strMsg, intFlags, strCaption, MSGERR_WARNING)
  1282. End Function
  1283. '-----------------------------------------------------------
  1284. ' SUB: SetFormFont
  1285. '
  1286. ' Walks through all controls on specified form and
  1287. ' sets Font a font chosen according to the system locale
  1288. '
  1289. ' IN: [frm] - Form whose control fonts need to be set.
  1290. '-----------------------------------------------------------
  1291. '
  1292. Public Sub SetFormFont(frm As Form)
  1293.     Dim ctl As Control
  1294.     Dim fntSize As Integer
  1295.     Dim fntName As String
  1296.     Dim fntCharset As Integer
  1297.     Dim oFont As StdFont
  1298.     
  1299.     ' some controls may fail, so we will do a resume next...
  1300.     '
  1301.     On Error Resume Next
  1302.     
  1303.     ' get the font name, size, and charset
  1304.     '
  1305.     GetFontInfo fntName, fntSize, fntCharset
  1306.     
  1307.     'Create a new font object
  1308.     Set oFont = New StdFont
  1309.     With oFont
  1310.         .Name = fntName
  1311.         .Size = fntSize
  1312.         .Charset = fntCharset
  1313.     End With
  1314.     ' Set the form's font
  1315.     Set frm.Font = oFont
  1316.     '
  1317.     ' loop through each control and try to set its font property
  1318.     ' this may fail, but our error handling is shut off
  1319.     '
  1320.     For Each ctl In frm.Controls
  1321.         Set ctl.Font = oFont
  1322.     Next
  1323.     '
  1324.     ' get out, reset error handling
  1325.     '
  1326.     Set ctl = Nothing
  1327.     On Error GoTo 0
  1328.     Exit Sub
  1329.        
  1330. End Sub
  1331.  
  1332. '-----------------------------------------------------------
  1333. ' SUB:  GetFontInfo
  1334. '
  1335. ' Gets the best font to use according the current system's
  1336. ' locale.
  1337. '
  1338. ' OUT:  [sFont] - name of font
  1339. '       [nFont] - size of font
  1340. '       [nCharset] - character set of font to use
  1341. '-----------------------------------------------------------
  1342. Private Sub GetFontInfo(sFont As String, nFont As Integer, nCharSet As Integer)
  1343.     Dim LCID    As Integer
  1344.     Dim PLangId As Integer
  1345.     Dim sLangId As Integer
  1346.     ' if font is set, used the cached values
  1347.     If m_sFont <> "" Then
  1348.         sFont = m_sFont
  1349.         nFont = m_nFont
  1350.         nCharSet = m_nCharset
  1351.         Exit Sub
  1352.     End If
  1353.     
  1354.     ' font hasn't been set yet, need to get it now...
  1355.     LCID = GetSystemDefaultLCID                 ' get current system LCID
  1356.     PLangId = PRIMARYLANGID(LCID)               ' get LCID's Primary language id
  1357.     sLangId = SUBLANGID(LCID)                   ' get LCID's Sub language id
  1358.     
  1359.     Select Case PLangId                         ' determine primary language id
  1360.     Case LANG_CHINESE
  1361.         If (sLangId = SUBLANG_CHINESE_TRADITIONAL) Then
  1362.             sFont = ChrW$(&H65B0) & ChrW$(&H7D30) & ChrW$(&H660E) & ChrW$(&H9AD4)   ' New Ming-Li
  1363.             nFont = 9
  1364.             nCharSet = CHARSET_CHINESEBIG5
  1365.         ElseIf (sLangId = SUBLANG_CHINESE_SIMPLIFIED) Then
  1366.             sFont = ChrW$(&H5B8B) & ChrW$(&H4F53)
  1367.             nFont = 9
  1368.             nCharSet = CHARSET_CHINESESIMPLIFIED
  1369.         End If
  1370.     Case LANG_JAPANESE
  1371.         sFont = ChrW$(&HFF2D) & ChrW$(&HFF33) & ChrW$(&H20) & ChrW$(&HFF30) & _
  1372.                 ChrW$(&H30B4) & ChrW$(&H30B7) & ChrW$(&H30C3) & ChrW$(&H30AF)
  1373.         nFont = 9
  1374.         nCharSet = CHARSET_SHIFTJIS
  1375.     Case LANG_KOREAN
  1376.         If (sLangId = SUBLANG_KOREAN) Then
  1377.             sFont = ChrW$(&HAD74) & ChrW$(&HB9BC)
  1378.         ElseIf (sLangId = SUBLANG_KOREAN_JOHAB) Then
  1379.             sFont = ChrW$(&HAD74) & ChrW$(&HB9BC)
  1380.         End If
  1381.         nFont = 9
  1382.         nCharSet = CHARSET_HANGEUL
  1383.     Case Else
  1384.         sFont = "Tahoma"
  1385.         If Not IsFontSupported(sFont) Then
  1386.             'Tahoma is not on this machine.  This condition is very probably since
  1387.             'this is a setup program that may be run on a clean machine
  1388.             'Try Arial
  1389.             sFont = "Arial"
  1390.             If Not IsFontSupported(sFont) Then
  1391.                 'Arial isn't even on the machine.  This is an unusual situation that
  1392.                 'is caused by deliberate removal
  1393.                 'Try system
  1394.                 sFont = "System"
  1395.                 'If system isn't supported, allow the default font to be used
  1396.                 If Not IsFontSupported(sFont) Then
  1397.                     'If "System" is not supported, "IsFontSupported" will have
  1398.                     'output the default font in sFont
  1399.                 End If
  1400.             End If
  1401.         End If
  1402.         nFont = 8
  1403.         ' set the charset for the users default system Locale
  1404.         nCharSet = GetUserCharset
  1405.     End Select
  1406.     m_sFont = sFont
  1407.     m_nFont = nFont
  1408.     m_nCharset = nCharSet
  1409. '-------------------------------------------------------
  1410. End Sub
  1411. '-------------------------------------------------------
  1412.  
  1413. '------------------------------------------------------------
  1414. '- Language Functions...
  1415. '------------------------------------------------------------
  1416. Private Function PRIMARYLANGID(ByVal LCID As Integer) As Integer
  1417.     PRIMARYLANGID = (LCID And &H3FF)
  1418. End Function
  1419. Private Function SUBLANGID(ByVal LCID As Integer) As Integer
  1420.     SUBLANGID = (LCID / (2 ^ 10))
  1421. End Function
  1422.  
  1423. '-----------------------------------------------------------
  1424. ' Function: GetUserCharset
  1425. '
  1426. ' Get's the default user character set
  1427. '
  1428. ' OS: Win 95 & NT 4 or newer
  1429. '-----------------------------------------------------------
  1430. Private Function GetUserCharset() As Integer
  1431.     Dim ls  As LOCALESIGNATURE                              ' local signature struct.
  1432.     Dim ci  As CHARSETINFO                                  ' character set info struct.
  1433.     Dim rc  As Long                                         ' return code
  1434.     ' get locale signature based on the USER's Default LCID.
  1435.     rc = GetLocaleInfoLS(GetUserDefaultLCID, LOCALE_FONTSIGNATURE, ls, Len(ls))
  1436.     If (rc > 0) Then                                        ' if success
  1437.         ls.lsCsbDefault(1) = 0                              ' zero out bits
  1438.         
  1439.         ' translate charset info from locale fontsignature.
  1440.         rc = TranslateCharsetInfo(ls.lsCsbDefault(0), ci, TCI_SRCFONTSIG)
  1441.         If rc <> 0 Then GetUserCharset = ci.ciCharset       ' return charset
  1442.     End If
  1443. End Function
  1444.  
  1445. '-----------------------------------------------------------
  1446. ' Function: IsFontSupported
  1447. '
  1448. ' Validates a font name to make sure it is supported by
  1449. ' on the current system.
  1450. '
  1451. ' IN/OUT: [sFontName] - name of font to check, will also]
  1452. '         be set to the default font name if the provided
  1453. '         one is not supported.
  1454. '-----------------------------------------------------------
  1455. Private Function IsFontSupported(sFontName As String) As Boolean
  1456.     Dim oFont As StdFont
  1457.     On Error Resume Next
  1458.     Set oFont = New StdFont
  1459.     oFont.Name = sFontName
  1460.     IsFontSupported = (UCase(oFont.Name) = UCase(sFontName))
  1461.     sFontName = oFont.Name
  1462. End Function
  1463.  
  1464. '-----------------------------------------------------------
  1465. ' SUB: SetMousePtr
  1466. '
  1467. ' Provides a way to set the mouse pointer only when the
  1468. ' pointer state changes.  For every HOURGLASS call, there
  1469. ' should be a corresponding DEFAULT call.  Other types of
  1470. ' mouse pointers are set explicitly.
  1471. '
  1472. ' IN: [intMousePtr] - type of mouse pointer desired
  1473. '-----------------------------------------------------------
  1474. '
  1475. Sub SetMousePtr(intMousePtr As Integer)
  1476.     Static intPtrState As Integer
  1477.  
  1478.     Select Case intMousePtr
  1479.         Case vbHourglass
  1480.             intPtrState = intPtrState + 1
  1481.         Case gintMOUSE_DEFAULT
  1482.             intPtrState = intPtrState - 1
  1483.             If intPtrState < 0 Then
  1484.                 intPtrState = 0
  1485.             End If
  1486.         Case Else
  1487.             Screen.MousePointer = intMousePtr
  1488.             Exit Sub
  1489.         'End Case
  1490.     End Select
  1491.  
  1492.     Screen.MousePointer = IIf(intPtrState > 0, vbHourglass, gintMOUSE_DEFAULT)
  1493. End Sub
  1494.  
  1495. '-----------------------------------------------------------
  1496. ' FUNCTION: StripTerminator
  1497. '
  1498. ' Returns a string without any zero terminator.  Typically,
  1499. ' this was a string returned by a Windows API call.
  1500. '
  1501. ' IN: [strString] - String to remove terminator from
  1502. '
  1503. ' Returns: The value of the string passed in minus any
  1504. '          terminating zero.
  1505. '-----------------------------------------------------------
  1506. '
  1507. Function StripTerminator(ByVal strString As String) As String
  1508.     Dim intZeroPos As Integer
  1509.  
  1510.     intZeroPos = InStr(strString, Chr$(0))
  1511.     If intZeroPos > 0 Then
  1512.         StripTerminator = Left$(strString, intZeroPos - 1)
  1513.     Else
  1514.         StripTerminator = strString
  1515.     End If
  1516. End Function
  1517.  
  1518. '-----------------------------------------------------------
  1519. ' FUNCTION: GetFileVersion
  1520. '
  1521. ' Returns the internal file version number for the specified
  1522. ' file.  This can be different than the 'display' version
  1523. ' number shown in the File Manager File Properties dialog.
  1524. ' It is the same number as shown in the VB5 SetupWizard's
  1525. ' File Details screen.  This is the number used by the
  1526. ' Windows VerInstallFile API when comparing file versions.
  1527. '
  1528. ' IN: [strFilename] - the file whose version # is desired
  1529. '     [fIsRemoteServerSupportFile] - whether or not this file is
  1530. '          a remote ActiveX component support file (.VBR)
  1531. '          (Enterprise edition only).  If missing, False is assumed.
  1532. '
  1533. ' Returns: The Version number string if found, otherwise
  1534. '          vbnullstring
  1535. '-----------------------------------------------------------
  1536. '
  1537. Function GetFileVersion(ByVal strFilename As String, Optional ByVal fIsRemoteServerSupportFile As Boolean = False) As String
  1538.     Dim sVerInfo As VERINFO
  1539.     Dim strVer As String
  1540.  
  1541.     On Error GoTo GFVError
  1542.  
  1543.     '
  1544.     'Get the file version into a VERINFO struct, and then assemble a version string
  1545.     'from the appropriate elements.
  1546.     '
  1547.     If GetFileVerStruct(strFilename, sVerInfo, fIsRemoteServerSupportFile) = True Then
  1548.         strVer = Format$(sVerInfo.FileVerPart1) & gstrDECIMAL & Format$(sVerInfo.FileVerPart2) & gstrDECIMAL
  1549.         strVer = strVer & Format$(sVerInfo.FileVerPart3) & gstrDECIMAL & Format$(sVerInfo.FileVerPart4)
  1550.         GetFileVersion = strVer
  1551.     Else
  1552.         GetFileVersion = vbNullString
  1553.     End If
  1554.     
  1555.     Exit Function
  1556.     
  1557. GFVError:
  1558.     GetFileVersion = vbNullString
  1559.     Err = 0
  1560. End Function
  1561.  
  1562. '-----------------------------------------------------------
  1563. ' FUNCTION: GetFileVerStruct
  1564. '
  1565. ' Gets the file version information into a VERINFO TYPE
  1566. ' variable
  1567. '
  1568. ' IN: [strFilename] - name of file to get version info for
  1569. '     [fIsRemoteServerSupportFile] - whether or not this file is
  1570. '          a remote ActiveX component support file (.VBR)
  1571. '          (Enterprise edition only).  If missing, False is assumed.
  1572. ' OUT: [sVerInfo] - VERINFO Type to fill with version info
  1573. '
  1574. ' Returns: True if version info found, False otherwise
  1575. '-----------------------------------------------------------
  1576. '
  1577. Function GetFileVerStruct(ByVal sFile As String, sVer As VERINFO, Optional ByVal fIsRemoteServerSupportFile As Boolean = False) As Boolean
  1578.     Dim lVerSize As Long, lTemp As Long, lRet As Long
  1579.     Dim bInfo() As Byte
  1580.     Dim lpBuffer As Long
  1581.     Const sEXE As String * 1 = "\"
  1582.     Dim fFoundVer As Boolean
  1583.     
  1584.     GetFileVerStruct = False
  1585.     fFoundVer = False
  1586.     
  1587.     If fIsRemoteServerSupportFile Then
  1588.         GetFileVerStruct = GetRemoteSupportFileVerStruct(sFile, sVer)
  1589.         fFoundVer = True
  1590.     Else
  1591.         '
  1592.         'Get the size of the file version info, allocate a buffer for it, and get the
  1593.         'version info.  Next, we query the Fixed file info portion, where the internal
  1594.         'file version used by the Windows VerInstallFile API is kept.  We then copy
  1595.         'the fixed file info into a VERINFO structure.
  1596.         '
  1597.         lVerSize = GetFileVersionInfoSize(sFile, lTemp)
  1598.         ReDim bInfo(lVerSize)
  1599.         If lVerSize > 0 Then
  1600.             lRet = GetFileVersionInfo(sFile, lTemp, lVerSize, VarPtr(bInfo(0)))
  1601.             If lRet <> 0 Then
  1602.                 lRet = VerQueryValue(VarPtr(bInfo(0)), sEXE & vbNullChar, lpBuffer, lVerSize)
  1603.                 If lRet <> 0 Then
  1604.                     CopyMemory sVer, ByVal lpBuffer, lVerSize
  1605.                     fFoundVer = True
  1606.                     GetFileVerStruct = True
  1607.                 End If
  1608.             End If
  1609.         End If
  1610.     End If
  1611.     If Not fFoundVer Then
  1612.         '
  1613.         ' We were unsuccessful in finding the version info from the file.
  1614.         ' One possibility is that this is a dependency file.
  1615.         '
  1616.         If UCase(Extension(sFile)) = gstrEXT_DEP Then
  1617.             GetFileVerStruct = GetDepFileVerStruct(sFile, sVer)
  1618.         End If
  1619.     End If
  1620. End Function
  1621. '-----------------------------------------------------------
  1622. ' FUNCTION: GetFileDescription
  1623. '
  1624. ' Gets the file description information.
  1625. '
  1626. ' IN: [strFilename] - name of file to get description of.
  1627. '
  1628. ' Returns: Description (vbNullString if not found)
  1629. '-----------------------------------------------------------
  1630. '
  1631. Function GetFileDescription(ByVal sFile As String) As String
  1632.     Dim lVerSize As Long, lTemp As Long, lRet As Long
  1633.     Dim bInfo() As Byte
  1634.     Dim lpBuffer As Long
  1635.     Dim sDesc As String
  1636.     Dim sKEY As String
  1637.     Const sEXE As String = "\FileDescription"
  1638.     
  1639.     GetFileDescription = vbNullString
  1640.     
  1641.     '
  1642.     'Get the size of the file version info, allocate a buffer for it, and get the
  1643.     'version info.  Next, we query the Fixed file info portion, where the internal
  1644.     'file version used by the Windows VerInstallFile API is kept.  We then copy
  1645.     'the info into a string.
  1646.     '
  1647.     lVerSize = GetFileVersionInfoSize(sFile, lTemp)
  1648.     ReDim bInfo(lVerSize)
  1649.     If lVerSize > 0 Then
  1650.         lRet = GetFileVersionInfo(sFile, lTemp, lVerSize, VarPtr(bInfo(0)))
  1651.         If lRet <> 0 Then
  1652.             sKEY = GetNLSKey(bInfo)
  1653.             lRet = VerQueryValue(VarPtr(bInfo(0)), sKEY & sEXE, lpBuffer, lVerSize)
  1654.             If lRet <> 0 Then
  1655.                 sDesc = Space$(lVerSize)
  1656.                 lstrcpyn sDesc, lpBuffer, lVerSize
  1657.                 GetFileDescription = sDesc
  1658.             End If
  1659.         End If
  1660.     End If
  1661. End Function
  1662. Private Function GetNLSKey(byteVerData() As Byte) As String
  1663.     Const strTRANSLATION$ = "\VarFileInfo\Translation"
  1664.     Const strSTRINGFILEINFO$ = "\StringFileInfo\"
  1665.     Const strDEFAULTNLSKEY$ = "040904E4"
  1666.     Const LOCALE_IDEFAULTLANGUAGE& = &H9&
  1667.     Const LOCALE_IDEFAULTCODEPAGE& = &HB&
  1668.  
  1669.     Static strLANGCP As String
  1670.  
  1671.     Dim lpBufPtr As Long
  1672.     Dim strNLSKey As String
  1673.     Dim fGotNLSKey As Integer
  1674.     Dim intOffset As Integer
  1675.     Dim lVerSize As Long
  1676.     Dim ltmp As Long
  1677.     Dim lBufLen As Long
  1678.     Dim lLCID As Long
  1679.     Dim strTmp As String
  1680.  
  1681.     On Error GoTo GNLSKCleanup
  1682.  
  1683.     If VerQueryValue(VarPtr(byteVerData(0)), strTRANSLATION, lpBufPtr, lVerSize) <> 0 Then ' (Pass byteVerData array via reference to first element)
  1684.         If Len(strLANGCP) = 0 Then
  1685.             lLCID = GetUserDefaultLCID()
  1686.             If lLCID > 0 Then
  1687.                 strTmp = Space$(8)
  1688.     
  1689.                 GetLocaleInfoA lLCID, LOCALE_IDEFAULTCODEPAGE, strTmp, 8
  1690.                 strLANGCP = StripTerminator(strTmp)
  1691.                 While Len(strLANGCP) < 4
  1692.                     strLANGCP = gsZERO & strLANGCP
  1693.                 Wend
  1694.  
  1695.                 GetLocaleInfoA lLCID, LOCALE_IDEFAULTLANGUAGE, strTmp, 8
  1696.                 strLANGCP = StripTerminator(strTmp) & strLANGCP
  1697.                 While Len(strLANGCP) < 8
  1698.                     strLANGCP = gsZERO & strLANGCP
  1699.                 Wend
  1700.             End If
  1701.         End If
  1702.  
  1703.         If VerQueryValue(VarPtr(byteVerData(0)), strLANGCP, ltmp, lBufLen) <> 0 Then
  1704.             strNLSKey = strLANGCP
  1705.         Else
  1706.             For intOffset = 0 To lVerSize - 1 Step 4
  1707.                 CopyMemory ltmp, ByVal lpBufPtr + intOffset, 4
  1708.                 strTmp = Hex$(ltmp)
  1709.                 While Len(strTmp) < 8
  1710.                     strTmp = gsZERO & strTmp
  1711.                 Wend
  1712.  
  1713.                 strNLSKey = strSTRINGFILEINFO & Right$(strTmp, 4) & Left$(strTmp, 4)
  1714.  
  1715.                 If VerQueryValue(VarPtr(byteVerData(0)), strNLSKey, ltmp, lBufLen) <> 0 Then
  1716.                     fGotNLSKey = True
  1717.                     Exit For
  1718.                 End If
  1719.             Next
  1720.  
  1721.             If Not fGotNLSKey Then
  1722.                 strNLSKey = strSTRINGFILEINFO & strDEFAULTNLSKEY
  1723.                 If VerQueryValue(VarPtr(byteVerData(0)), strNLSKey, ltmp, lBufLen) <> 0 Then
  1724.                     fGotNLSKey = True
  1725.                 End If
  1726.             End If
  1727.         End If
  1728.     End If
  1729.  
  1730. GNLSKCleanup:
  1731.     If fGotNLSKey Then
  1732.         GetNLSKey = strNLSKey
  1733.     End If
  1734. End Function
  1735. '-----------------------------------------------------------
  1736. ' FUNCTION: GetDepFileVerStruct
  1737. '
  1738. ' Gets the file version information from a dependency
  1739. ' file (*.dep).  Such files do not have a Windows version
  1740. ' stamp, but they do have an internal version stamp that
  1741. ' we can look for.
  1742. '
  1743. ' IN: [strFilename] - name of dep file to get version info for
  1744. ' OUT: [sVerInfo] - VERINFO Type to fill with version info
  1745. '
  1746. ' Returns: True if version info found, False otherwise
  1747. '-----------------------------------------------------------
  1748. '
  1749. Function GetDepFileVerStruct(ByVal strFilename As String, sVerInfo As VERINFO) As Boolean
  1750.     Const strVersionKey = "Version="
  1751.     Dim cchVersionKey As Integer
  1752.     Dim iFile As Integer
  1753.  
  1754.     GetDepFileVerStruct = False
  1755.     
  1756.     cchVersionKey = Len(strVersionKey)
  1757.     sVerInfo.FileVerPart1 = gintNOVERINFO
  1758.     
  1759.     On Error GoTo Failed
  1760.     
  1761.     iFile = FreeFile
  1762.  
  1763.     Open strFilename For Input Access Read Lock Read Write As #iFile
  1764.     
  1765.     ' Loop through each line, looking for the key
  1766.     While (Not EOF(iFile))
  1767.         Dim strLine As String
  1768.  
  1769.         Line Input #iFile, strLine
  1770.         If Left$(strLine, cchVersionKey) = strVersionKey Then
  1771.             ' We've found the version key.  Copy everything after the equals sign
  1772.             Dim strVersion As String
  1773.             
  1774.             strVersion = Mid$(strLine, cchVersionKey + 1)
  1775.             
  1776.             'Parse and store the version information
  1777.             PackVerInfo strVersion, sVerInfo
  1778.  
  1779.             GetDepFileVerStruct = True
  1780.             Close iFile
  1781.             Exit Function
  1782.         End If
  1783.     Wend
  1784.     
  1785.     Close iFile
  1786.     Exit Function
  1787.  
  1788. Failed:
  1789.     GetDepFileVerStruct = False
  1790. End Function
  1791.  
  1792. '-----------------------------------------------------------
  1793. ' FUNCTION: GetRemoteSupportFileVerStruct
  1794. '
  1795. ' Gets the file version information of a remote ActiveX component
  1796. ' support file into a VERINFO TYPE variable (Enterprise
  1797. ' Edition only).  Such files do not have a Windows version
  1798. ' stamp, but they do have an internal version stamp that
  1799. ' we can look for.
  1800. '
  1801. ' IN: [strFilename] - name of file to get version info for
  1802. ' OUT: [sVerInfo] - VERINFO Type to fill with version info
  1803. '
  1804. ' Returns: True if version info found, False otherwise
  1805. '-----------------------------------------------------------
  1806. '
  1807. Function GetRemoteSupportFileVerStruct(ByVal strFilename As String, sVerInfo As VERINFO) As Boolean
  1808.     Const strVersionKey = "Version="
  1809.     Dim cchVersionKey As Integer
  1810.     Dim iFile As Integer
  1811.  
  1812.     cchVersionKey = Len(strVersionKey)
  1813.     sVerInfo.FileVerPart1 = gintNOVERINFO
  1814.     
  1815.     On Error GoTo Failed
  1816.     
  1817.     iFile = FreeFile
  1818.  
  1819.     Open strFilename For Input Access Read Lock Read Write As #iFile
  1820.     
  1821.     ' Loop through each line, looking for the key
  1822.     While (Not EOF(iFile))
  1823.         Dim strLine As String
  1824.  
  1825.         Line Input #iFile, strLine
  1826.         If Left$(strLine, cchVersionKey) = strVersionKey Then
  1827.             ' We've found the version key.  Copy everything after the equals sign
  1828.             Dim strVersion As String
  1829.             
  1830.             strVersion = Mid$(strLine, cchVersionKey + 1)
  1831.             
  1832.             'Parse and store the version information
  1833.             PackVerInfo strVersion, sVerInfo
  1834.  
  1835.             'Convert the format 1.2.3 from the .VBR into
  1836.             '1.2.0.3, which is really want we want
  1837.             sVerInfo.FileVerPart4 = sVerInfo.FileVerPart3
  1838.             sVerInfo.FileVerPart3 = 0
  1839.             
  1840.             GetRemoteSupportFileVerStruct = True
  1841.             Close iFile
  1842.             Exit Function
  1843.         End If
  1844.     Wend
  1845.     
  1846.     Close iFile
  1847.     Exit Function
  1848.  
  1849. Failed:
  1850.     GetRemoteSupportFileVerStruct = False
  1851. End Function
  1852. '-----------------------------------------------------------
  1853. ' FUNCTION: GetWindowsFontDir
  1854. '
  1855. ' Calls the windows API to get the windows font directory
  1856. ' and ensures that a trailing dir separator is present
  1857. '
  1858. ' Returns: The windows font directory
  1859. '-----------------------------------------------------------
  1860. '
  1861. Function GetWindowsFontDir() As String
  1862.     Dim oMalloc As IVBMalloc
  1863.     Dim sPath   As String
  1864.     Dim IDL     As Long
  1865.     
  1866.     ' Fill the item id list with the pointer of each folder item, rtns 0 on success
  1867.     If SHGetSpecialFolderLocation(0, sfidFONTS, IDL) = NOERROR Then
  1868.         sPath = String$(gintMAX_PATH_LEN, 0)
  1869.         SHGetPathFromIDListA IDL, sPath
  1870.         SHGetMalloc oMalloc
  1871.         oMalloc.Free IDL
  1872.         sPath = StringFromBuffer(sPath)
  1873.     End If
  1874.     AddDirSep sPath
  1875.  
  1876.     GetWindowsFontDir = sPath
  1877. End Function
  1878.  
  1879. '-----------------------------------------------------------
  1880. ' FUNCTION: GetWindowsDir
  1881. '
  1882. ' Calls the windows API to get the windows directory and
  1883. ' ensures that a trailing dir separator is present
  1884. '
  1885. ' Returns: The windows directory
  1886. '-----------------------------------------------------------
  1887. '
  1888. Function GetWindowsDir() As String
  1889.     Dim strBuf As String
  1890.  
  1891.     strBuf = Space$(gintMAX_SIZE)
  1892.  
  1893.     '
  1894.     'Get the windows directory and then trim the buffer to the exact length
  1895.     'returned and add a dir sep (backslash) if the API didn't return one
  1896.     '
  1897.     If GetWindowsDirectory(strBuf, gintMAX_SIZE) > 0 Then
  1898.         strBuf = StripTerminator$(strBuf)
  1899.         AddDirSep strBuf
  1900.  
  1901.         GetWindowsDir = strBuf
  1902.     Else
  1903.         GetWindowsDir = vbNullString
  1904.     End If
  1905. End Function
  1906.  
  1907. '-----------------------------------------------------------
  1908. ' FUNCTION: ExtractFilenameItem
  1909. '
  1910. ' Extracts a quoted or unquoted filename from a string.
  1911. '
  1912. ' IN: [str] - string to parse for a filename.
  1913. '     [intAnchor] - index in str at which the filename begins.
  1914. '             The filename continues to the end of the string
  1915. '             or up to the next comma in the string, or, if
  1916. '             the filename is enclosed in quotes, until the
  1917. '             next double quote.
  1918. ' OUT: Returns the filename, without quotes.
  1919. '      [intAnchor] is set to the comma, or else one character
  1920. '             past the end of the string
  1921. '      [fErr] is set to True if a parsing error is discovered
  1922. '
  1923. '-----------------------------------------------------------
  1924. '
  1925. Function strExtractFilenameItem(ByVal str As String, intAnchor As Integer, fErr As Boolean) As String
  1926.     While Mid$(str, intAnchor, 1) = " "
  1927.         intAnchor = intAnchor + 1
  1928.     Wend
  1929.     
  1930.     Dim iEndFilenamePos As Integer
  1931.     Dim strFilename As String
  1932.     If Mid$(str, intAnchor, 1) = """" Then
  1933.         ' Filename is surrounded by quotes
  1934.         iEndFilenamePos = InStr(intAnchor + 1, str, """") ' Find matching quote
  1935.         If iEndFilenamePos > 0 Then
  1936.             strFilename = Mid$(str, intAnchor + 1, iEndFilenamePos - 1 - intAnchor)
  1937.             intAnchor = iEndFilenamePos + 1
  1938.             While Mid$(str, intAnchor, 1) = " "
  1939.                 intAnchor = intAnchor + 1
  1940.             Wend
  1941.             If (Mid$(str, intAnchor, 1) <> gstrCOMMA) And (Mid$(str, intAnchor, 1) <> "") Then
  1942.                 fErr = True
  1943.                 Exit Function
  1944.             End If
  1945.         Else
  1946.             fErr = True
  1947.             Exit Function
  1948.         End If
  1949.     Else
  1950.         ' Filename continues until next comma or end of string
  1951.         Dim iCommaPos As Integer
  1952.         
  1953.         iCommaPos = InStr(intAnchor, str, gstrCOMMA)
  1954.         If iCommaPos = 0 Then
  1955.             iCommaPos = Len(str) + 1
  1956.         End If
  1957.         iEndFilenamePos = iCommaPos
  1958.         
  1959.         strFilename = Mid$(str, intAnchor, iEndFilenamePos - intAnchor)
  1960.         intAnchor = iCommaPos
  1961.     End If
  1962.     
  1963.     strFilename = Trim$(strFilename)
  1964.     If strFilename = "" Then
  1965.         fErr = True
  1966.         Exit Function
  1967.     End If
  1968.     
  1969.     fErr = False
  1970.     strExtractFilenameItem = strFilename
  1971. End Function
  1972.  
  1973. '-----------------------------------------------------------
  1974. ' FUNCTION: Extension
  1975. '
  1976. ' Extracts the extension portion of a file/path name
  1977. '
  1978. ' IN: [strFilename] - file/path to get the extension of
  1979. '
  1980. ' Returns: The extension if one exists, else vbnullstring
  1981. '-----------------------------------------------------------
  1982. '
  1983. Function Extension(ByVal strFilename As String) As String
  1984.     Dim intPos As Integer
  1985.  
  1986.     Extension = vbNullString
  1987.  
  1988.     intPos = Len(strFilename)
  1989.  
  1990.     Do While intPos > 0
  1991.         Select Case Mid$(strFilename, intPos, 1)
  1992.             Case gstrSEP_EXT
  1993.                 Extension = Mid$(strFilename, intPos + 1)
  1994.                 Exit Do
  1995.             Case gstrSEP_DIR, gstrSEP_DIRALT
  1996.                 Exit Do
  1997.             'End Case
  1998.         End Select
  1999.  
  2000.         intPos = intPos - 1
  2001.     Loop
  2002. End Function
  2003. Public Function BaseName(sPathandFile As String) As String
  2004.  
  2005.     '
  2006.     ' Strip the path from the file name, and just return the FileName
  2007.     ' Wraps the SeparatePathAndFileName from DWTools
  2008.     '
  2009.     Dim sPath As String
  2010.     Dim sFile As String
  2011.     
  2012.     SeparatePathAndFileName sPathandFile, sPath, sFile
  2013.     
  2014.     BaseName = sFile
  2015. End Function
  2016. 'Given a fully qualified filename, returns the path portion and the file
  2017. '   portion.
  2018. Public Sub SeparatePathAndFileName(FullPath As String, _
  2019.     Optional ByRef Path As String, _
  2020.     Optional ByRef FileName As String)
  2021.  
  2022.     Dim nSepPos As Long
  2023.     Dim sSEP As String
  2024.  
  2025.     nSepPos = Len(FullPath)
  2026.     sSEP = Mid$(FullPath, nSepPos, 1)
  2027.     Do Until IsSeparator(sSEP)
  2028.         nSepPos = nSepPos - 1
  2029.         If nSepPos = 0 Then Exit Do
  2030.         sSEP = Mid$(FullPath, nSepPos, 1)
  2031.     Loop
  2032.  
  2033.     Select Case nSepPos
  2034.         Case Len(FullPath)
  2035.             'Separator was found at the end of the full path. This is invalid.
  2036.         Case 0
  2037.             'Separator was not found.
  2038.             Path = CurDir$
  2039.             FileName = FullPath
  2040.         Case Else
  2041.             Path = Left$(FullPath, nSepPos - 1)
  2042.             FileName = Mid$(FullPath, nSepPos + 1)
  2043.     End Select
  2044. End Sub
  2045.  
  2046. '-----------------------------------------------------------
  2047. ' SUB: PackVerInfo
  2048. '
  2049. ' Parses a file version number string of the form
  2050. ' x[.x[.x[.x]]] and assigns the extracted numbers to the
  2051. ' appropriate elements of a VERINFO type variable.
  2052. ' Examples of valid version strings are '3.11.0.102',
  2053. ' '3.11', '3', etc.
  2054. '
  2055. ' IN: [strVersion] - version number string
  2056. '
  2057. ' OUT: [sVerInfo] - VERINFO type variable whose elements
  2058. '                   are assigned the appropriate numbers
  2059. '                   from the version number string
  2060. '-----------------------------------------------------------
  2061. '
  2062. Sub PackVerInfo(ByVal strVersion As String, sVerInfo As VERINFO)
  2063.     Dim intOffset As Integer
  2064.     Dim intAnchor As Integer
  2065.  
  2066.     On Error GoTo PVIError
  2067.  
  2068.     intOffset = InStr(strVersion, gstrDECIMAL)
  2069.     If intOffset = 0 Then
  2070.         sVerInfo.FileVerPart1 = Val(strVersion)
  2071.         GoTo PVIMSLo
  2072.     Else
  2073.         sVerInfo.FileVerPart1 = Val(Left$(strVersion, intOffset - 1))
  2074.         intAnchor = intOffset + 1
  2075.     End If
  2076.  
  2077.     intOffset = InStr(intAnchor, strVersion, gstrDECIMAL)
  2078.     If intOffset = 0 Then
  2079.         sVerInfo.FileVerPart2 = Val(Mid$(strVersion, intAnchor))
  2080.         GoTo PVILSHi
  2081.     Else
  2082.         sVerInfo.FileVerPart2 = Val(Mid$(strVersion, intAnchor, intOffset - intAnchor))
  2083.         intAnchor = intOffset + 1
  2084.     End If
  2085.  
  2086.     intOffset = InStr(intAnchor, strVersion, gstrDECIMAL)
  2087.     If intOffset = 0 Then
  2088.         sVerInfo.FileVerPart3 = Val(Mid$(strVersion, intAnchor))
  2089.         GoTo PVILSLo
  2090.     Else
  2091.         sVerInfo.FileVerPart3 = Val(Mid$(strVersion, intAnchor, intOffset - intAnchor))
  2092.         intAnchor = intOffset + 1
  2093.     End If
  2094.  
  2095.     intOffset = InStr(intAnchor, strVersion, gstrDECIMAL)
  2096.     If intOffset = 0 Then
  2097.         sVerInfo.FileVerPart4 = Val(Mid$(strVersion, intAnchor))
  2098.     Else
  2099.         sVerInfo.FileVerPart4 = Val(Mid$(strVersion, intAnchor, intOffset - intAnchor))
  2100.     End If
  2101.  
  2102.     Exit Sub
  2103.  
  2104. PVIError:
  2105.     sVerInfo.FileVerPart1 = 0
  2106. PVIMSLo:
  2107.     sVerInfo.FileVerPart2 = 0
  2108. PVILSHi:
  2109.     sVerInfo.FileVerPart3 = 0
  2110. PVILSLo:
  2111.     sVerInfo.FileVerPart4 = 0
  2112. End Sub
  2113.  
  2114. Public Function strQuoteString(strUnQuotedString As String, Optional vForce As Boolean = False, Optional vTrim As Boolean = True)
  2115. '
  2116. ' This routine adds quotation marks around an unquoted string, by default.  If the string is already quoted
  2117. ' it returns without making any changes unless vForce is set to True (vForce defaults to False) except that white
  2118. ' space before and after the quotes will be removed unless vTrim is False.  If the string contains leading or
  2119. ' trailing white space it is trimmed unless vTrim is set to False (vTrim defaults to True).
  2120. '
  2121.     Dim strQuotedString As String
  2122.     
  2123.     strQuotedString = strUnQuotedString
  2124.     '
  2125.     ' Trim the string if necessary
  2126.     '
  2127.     If vTrim Then
  2128.         strQuotedString = Trim(strQuotedString)
  2129.     End If
  2130.     '
  2131.     ' See if the string is already quoted
  2132.     '
  2133.     If Not vForce Then
  2134.         If (Left(strQuotedString, 1) = gstrQUOTE) And (Right(strQuotedString, 1) = gstrQUOTE) Then
  2135.             '
  2136.             ' String is already quoted.  We are done.
  2137.             '
  2138.             GoTo DoneQuoteString
  2139.         End If
  2140.     End If
  2141.     '
  2142.     ' Add the quotes
  2143.     '
  2144.     strQuotedString = gstrQUOTE & strQuotedString & gstrQUOTE
  2145. DoneQuoteString:
  2146.     strQuoteString = strQuotedString
  2147. End Function
  2148. Public Function strUnQuoteString(ByVal strQuotedString As String)
  2149. '
  2150. ' This routine tests to see if strQuotedString is wrapped in quotation
  2151. ' marks, and, if so, remove them.
  2152. '
  2153.     strQuotedString = Trim(strQuotedString)
  2154.  
  2155.     If Mid$(strQuotedString, 1, 1) = gstrQUOTE And Right$(strQuotedString, 1) = gstrQUOTE Then
  2156.         '
  2157.         ' It's quoted.  Get rid of the quotes.
  2158.         '
  2159.         strQuotedString = Mid$(strQuotedString, 2, Len(strQuotedString) - 2)
  2160.     End If
  2161.     strUnQuoteString = strQuotedString
  2162. End Function
  2163. Public Function fCheckFNLength(strFilename As String) As Boolean
  2164. '
  2165. ' This routine verifies that the length of the filename strFilename is valid.
  2166. ' Under NT (Intel) and Win95 it can be up to 259 (gintMAX_PATH_LEN-1) characters
  2167. ' long.  This length must include the drive, path, filename, commandline
  2168. ' arguments and quotes (if the string is quoted).
  2169. '
  2170.     fCheckFNLength = (Len(strFilename) < gintMAX_PATH_LEN)
  2171. End Function
  2172. Public Function intGetNextFldOffset(ByVal intAnchor As Integer, strList As String, strDelimit As String, Optional CompareType As Integer = 1) As Integer
  2173. '
  2174. ' This routine reads from a strDelimit separated list, strList, and locates the next
  2175. ' item in the list following intAnchor.  Basically it finds the next
  2176. ' occurance of strDelimit that is not inside quotes.  If strDelimit is not
  2177. ' found the routine returns 0.  Note intAnchor must be outside of quotes
  2178. ' or this routine will return incorrect results.
  2179. '
  2180. ' strDelimit is typically a comma.
  2181. '
  2182. ' If there is an error this routine returns -1.
  2183. '
  2184.     Dim intQuote As Integer
  2185.     Dim intDelimit As Integer
  2186.     
  2187.     Const CompareBinary = 0
  2188.     Const CompareText = 1
  2189.  
  2190.     If intAnchor = 0 Then intAnchor = 1
  2191.     
  2192.     intQuote = InStr(intAnchor, strList, gstrQUOTE, CompareType)
  2193.     intDelimit = InStr(intAnchor, strList, strDelimit, CompareType)
  2194.     
  2195.     If (intQuote > intDelimit) Or (intQuote = 0) Then
  2196.         '
  2197.         ' The next delimiter is not within quotes.  Therefore,
  2198.         ' we have found what we are looking for.  Note that the
  2199.         ' case where there are no delimiters is also handled here.
  2200.         '
  2201.         GoTo DoneGetNextFldOffset
  2202.     ElseIf intQuote < intDelimit Then
  2203.         '
  2204.         ' A quote appeared before the next delimiter.  This
  2205.         ' means we might be inside quotes.  We still need to check
  2206.         ' if the closing quote comes after the delmiter or not.
  2207.         '
  2208.         intAnchor = intQuote + 1
  2209.         intQuote = InStr(intAnchor, strList, gstrQUOTE, CompareType)
  2210.         If (intQuote > intDelimit) Then
  2211.             '
  2212.             ' The delimiter was inside quotes.  Therefore, ignore it.
  2213.             ' The next delimiter after the closing quote must be outside
  2214.             ' of quotes or else we have a corrupt file.
  2215.             '
  2216.             intAnchor = intQuote + 1
  2217.             intDelimit = InStr(intAnchor, strList, strDelimit, CompareType)
  2218.             '
  2219.             ' Sanity check.  Make sure there is not another quote before
  2220.             ' the delimiter we just found.
  2221.             '
  2222.             If intDelimit > 0 Then
  2223.                 intQuote = InStr(intAnchor, strList, gstrQUOTE, CompareType)
  2224.                 If (intQuote > 0) And (intQuote < intDelimit) Then
  2225.                     '
  2226.                     ' Something is wrong.  We've encountered a stray
  2227.                     ' quote.  Means the string is probably corrupt.
  2228.                     '
  2229.                     intDelimit = -1 ' Error
  2230.                 End If
  2231.             End If
  2232.         End If
  2233.     End If
  2234. DoneGetNextFldOffset:
  2235.     intGetNextFldOffset = intDelimit
  2236. End Function
  2237. Public Function LongPath(Path As String) As String
  2238.     Dim oDesktop As IVBShellFolder
  2239.     Dim nEaten As Long
  2240.     Dim pIdl As Long
  2241.     Dim sPath As String
  2242.     Dim oMalloc As IVBMalloc
  2243.  
  2244.     If Len(Path) > 0 Then
  2245.         SHGetDesktopFolder oDesktop
  2246.         oDesktop.ParseDisplayName 0, 0, Path, nEaten, pIdl, 0
  2247.         sPath = String$(gintMAX_PATH_LEN, 0)
  2248.         SHGetPathFromIDListA pIdl, sPath
  2249.         SHGetMalloc oMalloc
  2250.         oMalloc.Free pIdl
  2251.         LongPath = StringFromBuffer(sPath)
  2252.     End If
  2253. End Function
  2254.  
  2255. 'Try to convert a path to its long filename equivalent, but leave it unaltered
  2256. '   if we fail.
  2257. Public Sub MakeLongPath(Path As String)
  2258.     On Error Resume Next
  2259.     Path = LongPath(Path)
  2260. End Sub
  2261.  
  2262. Public Function StringFromBuffer(Buffer As String) As String
  2263.     Dim nPos As Long
  2264.  
  2265.     nPos = InStr(Buffer, Chr$(0))
  2266.     If nPos > 0 Then
  2267.         StringFromBuffer = Left$(Buffer, nPos - 1)
  2268.     Else
  2269.         StringFromBuffer = Buffer
  2270.     End If
  2271. End Function
  2272.  
  2273. ''==============================================================================
  2274. ''Code flow routines:
  2275.  
  2276. Public Function SyncShell(CommandLine As String, Optional Timeout As Long, _
  2277.     Optional WaitForInputIdle As Boolean, Optional Hide As Boolean = False) As Boolean
  2278.  
  2279.     Dim hProcess As Long
  2280.  
  2281.     Const STARTF_USESHOWWINDOW As Long = &H1
  2282.     Const SW_HIDE As Long = 0
  2283.     
  2284.     Dim ret As Long
  2285.     Dim nMilliseconds As Long
  2286.  
  2287.     If Timeout > 0 Then
  2288.         nMilliseconds = Timeout
  2289.     Else
  2290.         nMilliseconds = INFINITE
  2291.     End If
  2292.  
  2293.     hProcess = StartProcess(CommandLine, Hide)
  2294.  
  2295.     If WaitForInputIdle Then
  2296.         'Wait for the shelled application to finish setting up its UI:
  2297.         ret = InputIdle(hProcess, nMilliseconds)
  2298.     Else
  2299.         'Wait for the shelled application to terminate:
  2300.         ret = WaitForSingleObject(hProcess, nMilliseconds)
  2301.     End If
  2302.  
  2303.     CloseHandle hProcess
  2304.  
  2305.     'Return True if the application finished. Otherwise it timed out or erred.
  2306.     SyncShell = (ret = WAIT_OBJECT_0)
  2307. End Function
  2308.  
  2309. Public Function StartProcess(CommandLine As String, Optional Hide As Boolean = False) As Long
  2310.     Const STARTF_USESHOWWINDOW As Long = &H1
  2311.     Const SW_HIDE As Long = 0
  2312.     
  2313.     Dim proc As PROCESS_INFORMATION
  2314.     Dim Start As STARTUPINFO
  2315.  
  2316.     'Initialize the STARTUPINFO structure:
  2317.     Start.cb = Len(Start)
  2318.     If Hide Then
  2319.         Start.dwFlags = STARTF_USESHOWWINDOW
  2320.         Start.wShowWindow = SW_HIDE
  2321.     End If
  2322.     'Start the shelled application:
  2323.     CreateProcessA 0&, CommandLine, 0&, 0&, 1&, _
  2324.         NORMAL_PRIORITY_CLASS, 0&, 0&, Start, proc
  2325.  
  2326.     StartProcess = proc.hProcess
  2327. End Function
  2328. Public Function CheckDataAccess() As Boolean
  2329.     Dim i As Integer
  2330.     Dim sFile As FILEINFO
  2331.     Dim fData As Boolean
  2332.     fData = False
  2333.     i = 1
  2334.     Do While ReadSetupFileLine(gstrINI_FILES, i, sFile) = True
  2335.         If UCase(sFile.strSrcName) = UCase(gstrSEP_AMPERSAND & gstrFILE_MDAG) Then 'This is mdac_typ
  2336.             fData = True
  2337.             Exit Do
  2338.         End If
  2339.         i = i + 1
  2340.     Loop
  2341.     CheckDataAccess = fData
  2342. End Function
  2343. Public Sub InstallDataAccess()
  2344.  
  2345.     'Create the folder if it doesn't exist already.
  2346.     If Not (DirExists(gsTEMPDIR)) Then
  2347.         MkDir gsTEMPDIR
  2348.     End If
  2349.     ExtractFileFromCab GetShortPathName(gsCABNAME), gstrSEP_AMPERSAND & gstrFILE_MDAG, gsTEMPDIR & gstrFILE_MDAG, gintCabs, gstrSrcPath
  2350.     If FileExists(gsTEMPDIR & gstrFILE_MDAG) Then
  2351.         SyncShell gsTEMPDIR & gstrFILE_MDAG & gstrFILE_MDAGARGS, INFINITE
  2352.     End If
  2353.     
  2354. End Sub
  2355.